163b3bba8SJerry Jelinek /******************************************************************************
2*48ed61a7SRobert Mustacchi   SPDX-License-Identifier: BSD-3-Clause
363b3bba8SJerry Jelinek 
4*48ed61a7SRobert Mustacchi   Copyright (c) 2001-2017, Intel Corporation
563b3bba8SJerry Jelinek   All rights reserved.
6*48ed61a7SRobert Mustacchi 
7*48ed61a7SRobert Mustacchi   Redistribution and use in source and binary forms, with or without
863b3bba8SJerry Jelinek   modification, are permitted provided that the following conditions are met:
9*48ed61a7SRobert Mustacchi 
10*48ed61a7SRobert Mustacchi    1. Redistributions of source code must retain the above copyright notice,
1163b3bba8SJerry Jelinek       this list of conditions and the following disclaimer.
12*48ed61a7SRobert Mustacchi 
13*48ed61a7SRobert Mustacchi    2. Redistributions in binary form must reproduce the above copyright
14*48ed61a7SRobert Mustacchi       notice, this list of conditions and the following disclaimer in the
1563b3bba8SJerry Jelinek       documentation and/or other materials provided with the distribution.
16*48ed61a7SRobert Mustacchi 
17*48ed61a7SRobert Mustacchi    3. Neither the name of the Intel Corporation nor the names of its
18*48ed61a7SRobert Mustacchi       contributors may be used to endorse or promote products derived from
1963b3bba8SJerry Jelinek       this software without specific prior written permission.
20*48ed61a7SRobert Mustacchi 
2163b3bba8SJerry Jelinek   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22*48ed61a7SRobert Mustacchi   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*48ed61a7SRobert Mustacchi   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*48ed61a7SRobert Mustacchi   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25*48ed61a7SRobert Mustacchi   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26*48ed61a7SRobert Mustacchi   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27*48ed61a7SRobert Mustacchi   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*48ed61a7SRobert Mustacchi   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*48ed61a7SRobert Mustacchi   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3063b3bba8SJerry Jelinek   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3163b3bba8SJerry Jelinek   POSSIBILITY OF SUCH DAMAGE.
3263b3bba8SJerry Jelinek 
3363b3bba8SJerry Jelinek ******************************************************************************/
34dc0cb1cdSDale Ghent /*$FreeBSD$*/
3573cd555cSBin Tu - Sun Microsystems - Beijing China 
3673cd555cSBin Tu - Sun Microsystems - Beijing China #include "ixgbe_type.h"
3769b5a878SDan McDonald #include "ixgbe_82599.h"
3873cd555cSBin Tu - Sun Microsystems - Beijing China #include "ixgbe_api.h"
3973cd555cSBin Tu - Sun Microsystems - Beijing China #include "ixgbe_common.h"
4073cd555cSBin Tu - Sun Microsystems - Beijing China #include "ixgbe_phy.h"
4173cd555cSBin Tu - Sun Microsystems - Beijing China 
42dc0cb1cdSDale Ghent #define IXGBE_82599_MAX_TX_QUEUES 128
43dc0cb1cdSDale Ghent #define IXGBE_82599_MAX_RX_QUEUES 128
44dc0cb1cdSDale Ghent #define IXGBE_82599_RAR_ENTRIES   128
45dc0cb1cdSDale Ghent #define IXGBE_82599_MC_TBL_SIZE   128
46dc0cb1cdSDale Ghent #define IXGBE_82599_VFT_TBL_SIZE  128
47dc0cb1cdSDale Ghent #define IXGBE_82599_RX_PB_SIZE	  512
48dc0cb1cdSDale Ghent 
493cfa0eb9Schenlu chen - Sun Microsystems - Beijing China static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
5069b5a878SDan McDonald 					 ixgbe_link_speed speed,
5169b5a878SDan McDonald 					 bool autoneg_wait_to_complete);
52185c5677SPaul Guo static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
5369b5a878SDan McDonald static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
5469b5a878SDan McDonald 				   u16 offset, u16 *data);
5569b5a878SDan McDonald static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
5669b5a878SDan McDonald 					  u16 words, u16 *data);
57dc0cb1cdSDale Ghent static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
58dc0cb1cdSDale Ghent 					u8 dev_addr, u8 *data);
59dc0cb1cdSDale Ghent static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
60dc0cb1cdSDale Ghent 					u8 dev_addr, u8 data);
6173cd555cSBin Tu - Sun Microsystems - Beijing China 
ixgbe_init_mac_link_ops_82599(struct ixgbe_hw * hw)6263b3bba8SJerry Jelinek void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
6373cd555cSBin Tu - Sun Microsystems - Beijing China {
6473cd555cSBin Tu - Sun Microsystems - Beijing China 	struct ixgbe_mac_info *mac = &hw->mac;
6573cd555cSBin Tu - Sun Microsystems - Beijing China 
6673cd555cSBin Tu - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_init_mac_link_ops_82599");
6773cd555cSBin Tu - Sun Microsystems - Beijing China 
68dc0cb1cdSDale Ghent 	/*
69dc0cb1cdSDale Ghent 	 * enable the laser control functions for SFP+ fiber
70dc0cb1cdSDale Ghent 	 * and MNG not enabled
71dc0cb1cdSDale Ghent 	 */
72dc0cb1cdSDale Ghent 	if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
73dc0cb1cdSDale Ghent 	    !ixgbe_mng_enabled(hw)) {
745b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		mac->ops.disable_tx_laser =
75dc0cb1cdSDale Ghent 				       ixgbe_disable_tx_laser_multispeed_fiber;
765b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		mac->ops.enable_tx_laser =
77dc0cb1cdSDale Ghent 					ixgbe_enable_tx_laser_multispeed_fiber;
78dc0cb1cdSDale Ghent 		mac->ops.flap_tx_laser = ixgbe_flap_tx_laser_multispeed_fiber;
7963b3bba8SJerry Jelinek 
8073cd555cSBin Tu - Sun Microsystems - Beijing China 	} else {
815b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		mac->ops.disable_tx_laser = NULL;
825b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		mac->ops.enable_tx_laser = NULL;
835b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		mac->ops.flap_tx_laser = NULL;
8463b3bba8SJerry Jelinek 	}
8563b3bba8SJerry Jelinek 
8663b3bba8SJerry Jelinek 	if (hw->phy.multispeed_fiber) {
8763b3bba8SJerry Jelinek 		/* Set up dual speed SFP+ support */
88dc0cb1cdSDale Ghent 		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
89dc0cb1cdSDale Ghent 		mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599;
90dc0cb1cdSDale Ghent 		mac->ops.set_rate_select_speed =
91dc0cb1cdSDale Ghent 					       ixgbe_set_hard_rate_select_speed;
92dc0cb1cdSDale Ghent 		if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber_fixed)
93dc0cb1cdSDale Ghent 			mac->ops.set_rate_select_speed =
94dc0cb1cdSDale Ghent 					       ixgbe_set_soft_rate_select_speed;
9563b3bba8SJerry Jelinek 	} else {
963cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) &&
9763b3bba8SJerry Jelinek 		     (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
9863b3bba8SJerry Jelinek 		      hw->phy.smart_speed == ixgbe_smart_speed_on) &&
9963b3bba8SJerry Jelinek 		      !ixgbe_verify_lesm_fw_enabled_82599(hw)) {
100dc0cb1cdSDale Ghent 			mac->ops.setup_link = ixgbe_setup_mac_link_smartspeed;
10163b3bba8SJerry Jelinek 		} else {
102dc0cb1cdSDale Ghent 			mac->ops.setup_link = ixgbe_setup_mac_link_82599;
10363b3bba8SJerry Jelinek 		}
10473cd555cSBin Tu - Sun Microsystems - Beijing China 	}
10573cd555cSBin Tu - Sun Microsystems - Beijing China }
10673cd555cSBin Tu - Sun Microsystems - Beijing China 
10763b3bba8SJerry Jelinek /**
10863b3bba8SJerry Jelinek  *  ixgbe_init_phy_ops_82599 - PHY/SFP specific init
10963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
11073cd555cSBin Tu - Sun Microsystems - Beijing China  *
11163b3bba8SJerry Jelinek  *  Initialize any function pointers that were not able to be
11263b3bba8SJerry Jelinek  *  set during init_shared_code because the PHY/SFP type was
11363b3bba8SJerry Jelinek  *  not known.  Perform the SFP init if necessary.
11473cd555cSBin Tu - Sun Microsystems - Beijing China  *
11563b3bba8SJerry Jelinek  **/
ixgbe_init_phy_ops_82599(struct ixgbe_hw * hw)11663b3bba8SJerry Jelinek s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
11773cd555cSBin Tu - Sun Microsystems - Beijing China {
11873cd555cSBin Tu - Sun Microsystems - Beijing China 	struct ixgbe_mac_info *mac = &hw->mac;
11973cd555cSBin Tu - Sun Microsystems - Beijing China 	struct ixgbe_phy_info *phy = &hw->phy;
12073cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 ret_val = IXGBE_SUCCESS;
121dc0cb1cdSDale Ghent 	u32 esdp;
12273cd555cSBin Tu - Sun Microsystems - Beijing China 
12373cd555cSBin Tu - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_init_phy_ops_82599");
12473cd555cSBin Tu - Sun Microsystems - Beijing China 
125dc0cb1cdSDale Ghent 	if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
126dc0cb1cdSDale Ghent 		/* Store flag indicating I2C bus access control unit. */
127dc0cb1cdSDale Ghent 		hw->phy.qsfp_shared_i2c_bus = TRUE;
128dc0cb1cdSDale Ghent 
129dc0cb1cdSDale Ghent 		/* Initialize access to QSFP+ I2C bus */
130dc0cb1cdSDale Ghent 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
131dc0cb1cdSDale Ghent 		esdp |= IXGBE_ESDP_SDP0_DIR;
132dc0cb1cdSDale Ghent 		esdp &= ~IXGBE_ESDP_SDP1_DIR;
133dc0cb1cdSDale Ghent 		esdp &= ~IXGBE_ESDP_SDP0;
134dc0cb1cdSDale Ghent 		esdp &= ~IXGBE_ESDP_SDP0_NATIVE;
135dc0cb1cdSDale Ghent 		esdp &= ~IXGBE_ESDP_SDP1_NATIVE;
136dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
137dc0cb1cdSDale Ghent 		IXGBE_WRITE_FLUSH(hw);
138dc0cb1cdSDale Ghent 
139dc0cb1cdSDale Ghent 		phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_82599;
140dc0cb1cdSDale Ghent 		phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_82599;
141dc0cb1cdSDale Ghent 	}
14273cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Identify the PHY or SFP module */
14373cd555cSBin Tu - Sun Microsystems - Beijing China 	ret_val = phy->ops.identify(hw);
144185c5677SPaul Guo 	if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
145185c5677SPaul Guo 		goto init_phy_ops_out;
14673cd555cSBin Tu - Sun Microsystems - Beijing China 
14773cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Setup function pointers based on detected SFP module and speeds */
14873cd555cSBin Tu - Sun Microsystems - Beijing China 	ixgbe_init_mac_link_ops_82599(hw);
14973cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown)
15073cd555cSBin Tu - Sun Microsystems - Beijing China 		hw->phy.ops.reset = NULL;
15173cd555cSBin Tu - Sun Microsystems - Beijing China 
15273cd555cSBin Tu - Sun Microsystems - Beijing China 	/* If copper media, overwrite with copper function pointers */
15373cd555cSBin Tu - Sun Microsystems - Beijing China 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
154dc0cb1cdSDale Ghent 		mac->ops.setup_link = ixgbe_setup_copper_link_82599;
15573cd555cSBin Tu - Sun Microsystems - Beijing China 		mac->ops.get_link_capabilities =
156dc0cb1cdSDale Ghent 				  ixgbe_get_copper_link_capabilities_generic;
15773cd555cSBin Tu - Sun Microsystems - Beijing China 	}
15873cd555cSBin Tu - Sun Microsystems - Beijing China 
159dc0cb1cdSDale Ghent 	/* Set necessary function pointers based on PHY type */
16073cd555cSBin Tu - Sun Microsystems - Beijing China 	switch (hw->phy.type) {
16173cd555cSBin Tu - Sun Microsystems - Beijing China 	case ixgbe_phy_tn:
162dc0cb1cdSDale Ghent 		phy->ops.setup_link = ixgbe_setup_phy_link_tnx;
163dc0cb1cdSDale Ghent 		phy->ops.check_link = ixgbe_check_phy_link_tnx;
16473cd555cSBin Tu - Sun Microsystems - Beijing China 		phy->ops.get_firmware_version =
165dc0cb1cdSDale Ghent 			     ixgbe_get_phy_firmware_version_tnx;
166185c5677SPaul Guo 		break;
16773cd555cSBin Tu - Sun Microsystems - Beijing China 	default:
16873cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
16973cd555cSBin Tu - Sun Microsystems - Beijing China 	}
170185c5677SPaul Guo init_phy_ops_out:
17163b3bba8SJerry Jelinek 	return ret_val;
17273cd555cSBin Tu - Sun Microsystems - Beijing China }
17373cd555cSBin Tu - Sun Microsystems - Beijing China 
ixgbe_setup_sfp_modules_82599(struct ixgbe_hw * hw)17463b3bba8SJerry Jelinek s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
17573cd555cSBin Tu - Sun Microsystems - Beijing China {
17673cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 ret_val = IXGBE_SUCCESS;
17773cd555cSBin Tu - Sun Microsystems - Beijing China 	u16 list_offset, data_offset, data_value;
17873cd555cSBin Tu - Sun Microsystems - Beijing China 
17973cd555cSBin Tu - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_setup_sfp_modules_82599");
18073cd555cSBin Tu - Sun Microsystems - Beijing China 
18173cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
18273cd555cSBin Tu - Sun Microsystems - Beijing China 		ixgbe_init_mac_link_ops_82599(hw);
18373cd555cSBin Tu - Sun Microsystems - Beijing China 
18473cd555cSBin Tu - Sun Microsystems - Beijing China 		hw->phy.ops.reset = NULL;
18573cd555cSBin Tu - Sun Microsystems - Beijing China 
18673cd555cSBin Tu - Sun Microsystems - Beijing China 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
18769b5a878SDan McDonald 							      &data_offset);
18873cd555cSBin Tu - Sun Microsystems - Beijing China 		if (ret_val != IXGBE_SUCCESS)
18973cd555cSBin Tu - Sun Microsystems - Beijing China 			goto setup_sfp_out;
19073cd555cSBin Tu - Sun Microsystems - Beijing China 
191185c5677SPaul Guo 		/* PHY config will finish before releasing the semaphore */
19269b5a878SDan McDonald 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
19369b5a878SDan McDonald 							IXGBE_GSSR_MAC_CSR_SM);
194185c5677SPaul Guo 		if (ret_val != IXGBE_SUCCESS) {
195185c5677SPaul Guo 			ret_val = IXGBE_ERR_SWFW_SYNC;
196185c5677SPaul Guo 			goto setup_sfp_out;
197185c5677SPaul Guo 		}
198185c5677SPaul Guo 
199dc0cb1cdSDale Ghent 		if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
200dc0cb1cdSDale Ghent 			goto setup_sfp_err;
20173cd555cSBin Tu - Sun Microsystems - Beijing China 		while (data_value != 0xffff) {
20273cd555cSBin Tu - Sun Microsystems - Beijing China 			IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
20373cd555cSBin Tu - Sun Microsystems - Beijing China 			IXGBE_WRITE_FLUSH(hw);
204dc0cb1cdSDale Ghent 			if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
205dc0cb1cdSDale Ghent 				goto setup_sfp_err;
20673cd555cSBin Tu - Sun Microsystems - Beijing China 		}
207185c5677SPaul Guo 
208185c5677SPaul Guo 		/* Release the semaphore */
20969b5a878SDan McDonald 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
210dc0cb1cdSDale Ghent 		/* Delay obtaining semaphore again to allow FW access
211dc0cb1cdSDale Ghent 		 * prot_autoc_write uses the semaphore too.
212dc0cb1cdSDale Ghent 		 */
213185c5677SPaul Guo 		msec_delay(hw->eeprom.semaphore_delay);
21463b3bba8SJerry Jelinek 
215dc0cb1cdSDale Ghent 		/* Restart DSP and set SFI mode */
216dc0cb1cdSDale Ghent 		ret_val = hw->mac.ops.prot_autoc_write(hw,
217dc0cb1cdSDale Ghent 			hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL,
218dc0cb1cdSDale Ghent 			FALSE);
21963b3bba8SJerry Jelinek 
220dc0cb1cdSDale Ghent 		if (ret_val) {
22163b3bba8SJerry Jelinek 			DEBUGOUT("sfp module setup not complete\n");
22263b3bba8SJerry Jelinek 			ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
22363b3bba8SJerry Jelinek 			goto setup_sfp_out;
22463b3bba8SJerry Jelinek 		}
22563b3bba8SJerry Jelinek 
22673cd555cSBin Tu - Sun Microsystems - Beijing China 	}
22773cd555cSBin Tu - Sun Microsystems - Beijing China 
22873cd555cSBin Tu - Sun Microsystems - Beijing China setup_sfp_out:
22963b3bba8SJerry Jelinek 	return ret_val;
230dc0cb1cdSDale Ghent 
231dc0cb1cdSDale Ghent setup_sfp_err:
232dc0cb1cdSDale Ghent 	/* Release the semaphore */
233dc0cb1cdSDale Ghent 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
234dc0cb1cdSDale Ghent 	/* Delay obtaining semaphore again to allow FW access */
235dc0cb1cdSDale Ghent 	msec_delay(hw->eeprom.semaphore_delay);
236dc0cb1cdSDale Ghent 	ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
237dc0cb1cdSDale Ghent 		      "eeprom read at offset %d failed", data_offset);
238dc0cb1cdSDale Ghent 	return IXGBE_ERR_PHY;
239dc0cb1cdSDale Ghent }
240dc0cb1cdSDale Ghent 
241dc0cb1cdSDale Ghent /**
242dc0cb1cdSDale Ghent  *  prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read
243dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
244dc0cb1cdSDale Ghent  *  @locked: Return the if we locked for this read.
245dc0cb1cdSDale Ghent  *  @reg_val: Value we read from AUTOC
246dc0cb1cdSDale Ghent  *
247dc0cb1cdSDale Ghent  *  For this part (82599) we need to wrap read-modify-writes with a possible
248dc0cb1cdSDale Ghent  *  FW/SW lock.  It is assumed this lock will be freed with the next
249dc0cb1cdSDale Ghent  *  prot_autoc_write_82599().
250dc0cb1cdSDale Ghent  */
prot_autoc_read_82599(struct ixgbe_hw * hw,bool * locked,u32 * reg_val)251dc0cb1cdSDale Ghent s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked, u32 *reg_val)
252dc0cb1cdSDale Ghent {
253dc0cb1cdSDale Ghent 	s32 ret_val;
254dc0cb1cdSDale Ghent 
255dc0cb1cdSDale Ghent 	*locked = FALSE;
256dc0cb1cdSDale Ghent 	 /* If LESM is on then we need to hold the SW/FW semaphore. */
257dc0cb1cdSDale Ghent 	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
258dc0cb1cdSDale Ghent 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
259dc0cb1cdSDale Ghent 					IXGBE_GSSR_MAC_CSR_SM);
260dc0cb1cdSDale Ghent 		if (ret_val != IXGBE_SUCCESS)
261dc0cb1cdSDale Ghent 			return IXGBE_ERR_SWFW_SYNC;
262dc0cb1cdSDale Ghent 
263dc0cb1cdSDale Ghent 		*locked = TRUE;
264dc0cb1cdSDale Ghent 	}
265dc0cb1cdSDale Ghent 
266dc0cb1cdSDale Ghent 	*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
267dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
268dc0cb1cdSDale Ghent }
269dc0cb1cdSDale Ghent 
270dc0cb1cdSDale Ghent /**
271dc0cb1cdSDale Ghent  * prot_autoc_write_82599 - Hides MAC differences needed for AUTOC write
272dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
273*48ed61a7SRobert Mustacchi  * @autoc: value to write to AUTOC
274dc0cb1cdSDale Ghent  * @locked: bool to indicate whether the SW/FW lock was already taken by
275dc0cb1cdSDale Ghent  *           previous proc_autoc_read_82599.
276dc0cb1cdSDale Ghent  *
277dc0cb1cdSDale Ghent  * This part (82599) may need to hold the SW/FW lock around all writes to
278dc0cb1cdSDale Ghent  * AUTOC. Likewise after a write we need to do a pipeline reset.
279dc0cb1cdSDale Ghent  */
prot_autoc_write_82599(struct ixgbe_hw * hw,u32 autoc,bool locked)280dc0cb1cdSDale Ghent s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 autoc, bool locked)
281dc0cb1cdSDale Ghent {
282dc0cb1cdSDale Ghent 	s32 ret_val = IXGBE_SUCCESS;
283dc0cb1cdSDale Ghent 
284dc0cb1cdSDale Ghent 	/* Blocked by MNG FW so bail */
285dc0cb1cdSDale Ghent 	if (ixgbe_check_reset_blocked(hw))
286dc0cb1cdSDale Ghent 		goto out;
287dc0cb1cdSDale Ghent 
288dc0cb1cdSDale Ghent 	/* We only need to get the lock if:
289dc0cb1cdSDale Ghent 	 *  - We didn't do it already (in the read part of a read-modify-write)
290dc0cb1cdSDale Ghent 	 *  - LESM is enabled.
291dc0cb1cdSDale Ghent 	 */
292dc0cb1cdSDale Ghent 	if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) {
293dc0cb1cdSDale Ghent 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
294dc0cb1cdSDale Ghent 					IXGBE_GSSR_MAC_CSR_SM);
295dc0cb1cdSDale Ghent 		if (ret_val != IXGBE_SUCCESS)
296dc0cb1cdSDale Ghent 			return IXGBE_ERR_SWFW_SYNC;
297dc0cb1cdSDale Ghent 
298dc0cb1cdSDale Ghent 		locked = TRUE;
299dc0cb1cdSDale Ghent 	}
300dc0cb1cdSDale Ghent 
301dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
302dc0cb1cdSDale Ghent 	ret_val = ixgbe_reset_pipeline_82599(hw);
303dc0cb1cdSDale Ghent 
304dc0cb1cdSDale Ghent out:
305dc0cb1cdSDale Ghent 	/* Free the SW/FW semaphore as we either grabbed it here or
306dc0cb1cdSDale Ghent 	 * already had it when this function was called.
307dc0cb1cdSDale Ghent 	 */
308dc0cb1cdSDale Ghent 	if (locked)
309dc0cb1cdSDale Ghent 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
310dc0cb1cdSDale Ghent 
311dc0cb1cdSDale Ghent 	return ret_val;
31273cd555cSBin Tu - Sun Microsystems - Beijing China }
31373cd555cSBin Tu - Sun Microsystems - Beijing China 
31463b3bba8SJerry Jelinek /**
31563b3bba8SJerry Jelinek  *  ixgbe_init_ops_82599 - Inits func ptrs and MAC type
31663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
31773cd555cSBin Tu - Sun Microsystems - Beijing China  *
31863b3bba8SJerry Jelinek  *  Initialize the function pointers and assign the MAC type for 82599.
31963b3bba8SJerry Jelinek  *  Does not touch the hardware.
32063b3bba8SJerry Jelinek  **/
32173cd555cSBin Tu - Sun Microsystems - Beijing China 
ixgbe_init_ops_82599(struct ixgbe_hw * hw)32263b3bba8SJerry Jelinek s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
32373cd555cSBin Tu - Sun Microsystems - Beijing China {
32473cd555cSBin Tu - Sun Microsystems - Beijing China 	struct ixgbe_mac_info *mac = &hw->mac;
32573cd555cSBin Tu - Sun Microsystems - Beijing China 	struct ixgbe_phy_info *phy = &hw->phy;
32669b5a878SDan McDonald 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
32773cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 ret_val;
32873cd555cSBin Tu - Sun Microsystems - Beijing China 
3293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_init_ops_82599");
3303cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
331dc0cb1cdSDale Ghent 	ixgbe_init_phy_ops_generic(hw);
33273cd555cSBin Tu - Sun Microsystems - Beijing China 	ret_val = ixgbe_init_ops_generic(hw);
33373cd555cSBin Tu - Sun Microsystems - Beijing China 
33473cd555cSBin Tu - Sun Microsystems - Beijing China 	/* PHY */
335dc0cb1cdSDale Ghent 	phy->ops.identify = ixgbe_identify_phy_82599;
336dc0cb1cdSDale Ghent 	phy->ops.init = ixgbe_init_phy_ops_82599;
33773cd555cSBin Tu - Sun Microsystems - Beijing China 
33873cd555cSBin Tu - Sun Microsystems - Beijing China 	/* MAC */
339dc0cb1cdSDale Ghent 	mac->ops.reset_hw = ixgbe_reset_hw_82599;
340dc0cb1cdSDale Ghent 	mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_gen2;
341dc0cb1cdSDale Ghent 	mac->ops.get_media_type = ixgbe_get_media_type_82599;
34273cd555cSBin Tu - Sun Microsystems - Beijing China 	mac->ops.get_supported_physical_layer =
343dc0cb1cdSDale Ghent 				    ixgbe_get_supported_physical_layer_82599;
344dc0cb1cdSDale Ghent 	mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic;
345dc0cb1cdSDale Ghent 	mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic;
346dc0cb1cdSDale Ghent 	mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_82599;
347dc0cb1cdSDale Ghent 	mac->ops.read_analog_reg8 = ixgbe_read_analog_reg8_82599;
348dc0cb1cdSDale Ghent 	mac->ops.write_analog_reg8 = ixgbe_write_analog_reg8_82599;
349dc0cb1cdSDale Ghent 	mac->ops.start_hw = ixgbe_start_hw_82599;
350dc0cb1cdSDale Ghent 	mac->ops.get_san_mac_addr = ixgbe_get_san_mac_addr_generic;
351dc0cb1cdSDale Ghent 	mac->ops.set_san_mac_addr = ixgbe_set_san_mac_addr_generic;
352dc0cb1cdSDale Ghent 	mac->ops.get_device_caps = ixgbe_get_device_caps_generic;
353dc0cb1cdSDale Ghent 	mac->ops.get_wwn_prefix = ixgbe_get_wwn_prefix_generic;
354dc0cb1cdSDale Ghent 	mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic;
355dc0cb1cdSDale Ghent 	mac->ops.prot_autoc_read = prot_autoc_read_82599;
356dc0cb1cdSDale Ghent 	mac->ops.prot_autoc_write = prot_autoc_write_82599;
35773cd555cSBin Tu - Sun Microsystems - Beijing China 
35873cd555cSBin Tu - Sun Microsystems - Beijing China 	/* RAR, Multicast, VLAN */
359dc0cb1cdSDale Ghent 	mac->ops.set_vmdq = ixgbe_set_vmdq_generic;
360dc0cb1cdSDale Ghent 	mac->ops.set_vmdq_san_mac = ixgbe_set_vmdq_san_mac_generic;
361dc0cb1cdSDale Ghent 	mac->ops.clear_vmdq = ixgbe_clear_vmdq_generic;
362dc0cb1cdSDale Ghent 	mac->ops.insert_mac_addr = ixgbe_insert_mac_addr_generic;
36373cd555cSBin Tu - Sun Microsystems - Beijing China 	mac->rar_highwater = 1;
364dc0cb1cdSDale Ghent 	mac->ops.set_vfta = ixgbe_set_vfta_generic;
365dc0cb1cdSDale Ghent 	mac->ops.set_vlvf = ixgbe_set_vlvf_generic;
366dc0cb1cdSDale Ghent 	mac->ops.clear_vfta = ixgbe_clear_vfta_generic;
367dc0cb1cdSDale Ghent 	mac->ops.init_uta_tables = ixgbe_init_uta_tables_generic;
368dc0cb1cdSDale Ghent 	mac->ops.setup_sfp = ixgbe_setup_sfp_modules_82599;
369dc0cb1cdSDale Ghent 	mac->ops.set_mac_anti_spoofing = ixgbe_set_mac_anti_spoofing;
370dc0cb1cdSDale Ghent 	mac->ops.set_vlan_anti_spoofing = ixgbe_set_vlan_anti_spoofing;
37173cd555cSBin Tu - Sun Microsystems - Beijing China 
37273cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Link */
373dc0cb1cdSDale Ghent 	mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82599;
374dc0cb1cdSDale Ghent 	mac->ops.check_link = ixgbe_check_mac_link_generic;
375dc0cb1cdSDale Ghent 	mac->ops.setup_rxpba = ixgbe_set_rxpba_generic;
37673cd555cSBin Tu - Sun Microsystems - Beijing China 	ixgbe_init_mac_link_ops_82599(hw);
37773cd555cSBin Tu - Sun Microsystems - Beijing China 
378dc0cb1cdSDale Ghent 	mac->mcft_size		= IXGBE_82599_MC_TBL_SIZE;
379dc0cb1cdSDale Ghent 	mac->vft_size		= IXGBE_82599_VFT_TBL_SIZE;
380dc0cb1cdSDale Ghent 	mac->num_rar_entries	= IXGBE_82599_RAR_ENTRIES;
381dc0cb1cdSDale Ghent 	mac->rx_pb_size		= IXGBE_82599_RX_PB_SIZE;
382dc0cb1cdSDale Ghent 	mac->max_rx_queues	= IXGBE_82599_MAX_RX_QUEUES;
383dc0cb1cdSDale Ghent 	mac->max_tx_queues	= IXGBE_82599_MAX_TX_QUEUES;
38469b5a878SDan McDonald 	mac->max_msix_vectors	= ixgbe_get_pcie_msix_count_generic(hw);
38569b5a878SDan McDonald 
386dc0cb1cdSDale Ghent 	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
387dc0cb1cdSDale Ghent 				      & IXGBE_FWSM_MODE_MASK);
38869b5a878SDan McDonald 
38969b5a878SDan McDonald 	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
39069b5a878SDan McDonald 
39169b5a878SDan McDonald 	/* EEPROM */
392dc0cb1cdSDale Ghent 	eeprom->ops.read = ixgbe_read_eeprom_82599;
393dc0cb1cdSDale Ghent 	eeprom->ops.read_buffer = ixgbe_read_eeprom_buffer_82599;
39469b5a878SDan McDonald 
39569b5a878SDan McDonald 	/* Manageability interface */
396dc0cb1cdSDale Ghent 	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic;
397dc0cb1cdSDale Ghent 
398*48ed61a7SRobert Mustacchi 	mac->ops.bypass_rw = ixgbe_bypass_rw_generic;
399*48ed61a7SRobert Mustacchi 	mac->ops.bypass_valid_rd = ixgbe_bypass_valid_rd_generic;
400*48ed61a7SRobert Mustacchi 	mac->ops.bypass_set = ixgbe_bypass_set_generic;
401*48ed61a7SRobert Mustacchi 	mac->ops.bypass_rd_eep = ixgbe_bypass_rd_eep_generic;
40269b5a878SDan McDonald 
403dc0cb1cdSDale Ghent 	mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
40473cd555cSBin Tu - Sun Microsystems - Beijing China 
40563b3bba8SJerry Jelinek 	return ret_val;
40673cd555cSBin Tu - Sun Microsystems - Beijing China }
40773cd555cSBin Tu - Sun Microsystems - Beijing China 
40863b3bba8SJerry Jelinek /**
40963b3bba8SJerry Jelinek  *  ixgbe_get_link_capabilities_82599 - Determines link capabilities
41063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
41163b3bba8SJerry Jelinek  *  @speed: pointer to link speed
412dc0cb1cdSDale Ghent  *  @autoneg: TRUE when autoneg or autotry is enabled
41373cd555cSBin Tu - Sun Microsystems - Beijing China  *
41463b3bba8SJerry Jelinek  *  Determines the link capabilities by reading the AUTOC register.
41563b3bba8SJerry Jelinek  **/
ixgbe_get_link_capabilities_82599(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)41663b3bba8SJerry Jelinek s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
41769b5a878SDan McDonald 				      ixgbe_link_speed *speed,
418dc0cb1cdSDale Ghent 				      bool *autoneg)
41973cd555cSBin Tu - Sun Microsystems - Beijing China {
42073cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 status = IXGBE_SUCCESS;
42173cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 autoc = 0;
42273cd555cSBin Tu - Sun Microsystems - Beijing China 
4233cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_link_capabilities_82599");
4243cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
42563b3bba8SJerry Jelinek 
4265b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/* Check if 1G SFP module. */
4275b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
42869b5a878SDan McDonald 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
429eb341807SSaso Kiselkov 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
430eb341807SSaso Kiselkov 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
43169b5a878SDan McDonald 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
43269b5a878SDan McDonald 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
4335b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
434dc0cb1cdSDale Ghent 		*autoneg = TRUE;
4355b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		goto out;
4365b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	}
4375b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43873cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
43973cd555cSBin Tu - Sun Microsystems - Beijing China 	 * Determine link capabilities based on the stored value of AUTOC,
44073cd555cSBin Tu - Sun Microsystems - Beijing China 	 * which represents EEPROM defaults.  If AUTOC value has not
44173cd555cSBin Tu - Sun Microsystems - Beijing China 	 * been stored, use the current register values.
44273cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
44373cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->mac.orig_link_settings_stored)
44473cd555cSBin Tu - Sun Microsystems - Beijing China 		autoc = hw->mac.orig_autoc;
44573cd555cSBin Tu - Sun Microsystems - Beijing China 	else
44673cd555cSBin Tu - Sun Microsystems - Beijing China 		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
44773cd555cSBin Tu - Sun Microsystems - Beijing China 
44873cd555cSBin Tu - Sun Microsystems - Beijing China 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
44973cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
45073cd555cSBin Tu - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
451dc0cb1cdSDale Ghent 		*autoneg = FALSE;
45273cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
45373cd555cSBin Tu - Sun Microsystems - Beijing China 
45473cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
45573cd555cSBin Tu - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
456dc0cb1cdSDale Ghent 		*autoneg = FALSE;
45773cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
45873cd555cSBin Tu - Sun Microsystems - Beijing China 
45973cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_1G_AN:
46073cd555cSBin Tu - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
461dc0cb1cdSDale Ghent 		*autoneg = TRUE;
46273cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
46373cd555cSBin Tu - Sun Microsystems - Beijing China 
46473cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_10G_SERIAL:
46573cd555cSBin Tu - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
466dc0cb1cdSDale Ghent 		*autoneg = FALSE;
46773cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
46873cd555cSBin Tu - Sun Microsystems - Beijing China 
46973cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
47073cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
47173cd555cSBin Tu - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
47273cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KR_SUPP)
47373cd555cSBin Tu - Sun Microsystems - Beijing China 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
47473cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
47573cd555cSBin Tu - Sun Microsystems - Beijing China 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
47673cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KX_SUPP)
47773cd555cSBin Tu - Sun Microsystems - Beijing China 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
478dc0cb1cdSDale Ghent 		*autoneg = TRUE;
47973cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
48073cd555cSBin Tu - Sun Microsystems - Beijing China 
48173cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII:
48273cd555cSBin Tu - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_100_FULL;
48373cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KR_SUPP)
48473cd555cSBin Tu - Sun Microsystems - Beijing China 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
48573cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
48673cd555cSBin Tu - Sun Microsystems - Beijing China 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
48773cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KX_SUPP)
48873cd555cSBin Tu - Sun Microsystems - Beijing China 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
489dc0cb1cdSDale Ghent 		*autoneg = TRUE;
49073cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
49173cd555cSBin Tu - Sun Microsystems - Beijing China 
49273cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_SGMII_1G_100M:
49373cd555cSBin Tu - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL;
494dc0cb1cdSDale Ghent 		*autoneg = FALSE;
49573cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
49673cd555cSBin Tu - Sun Microsystems - Beijing China 
49773cd555cSBin Tu - Sun Microsystems - Beijing China 	default:
49873cd555cSBin Tu - Sun Microsystems - Beijing China 		status = IXGBE_ERR_LINK_SETUP;
49973cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
500dc0cb1cdSDale Ghent 		break;
50173cd555cSBin Tu - Sun Microsystems - Beijing China 	}
50273cd555cSBin Tu - Sun Microsystems - Beijing China 
50373cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->phy.multispeed_fiber) {
50473cd555cSBin Tu - Sun Microsystems - Beijing China 		*speed |= IXGBE_LINK_SPEED_10GB_FULL |
50569b5a878SDan McDonald 			  IXGBE_LINK_SPEED_1GB_FULL;
506dc0cb1cdSDale Ghent 
507dc0cb1cdSDale Ghent 		/* QSFP must not enable full auto-negotiation
508dc0cb1cdSDale Ghent 		 * Limited autoneg is enabled at 1G
509dc0cb1cdSDale Ghent 		 */
510dc0cb1cdSDale Ghent 		if (hw->phy.media_type == ixgbe_media_type_fiber_qsfp)
511dc0cb1cdSDale Ghent 			*autoneg = FALSE;
512dc0cb1cdSDale Ghent 		else
513dc0cb1cdSDale Ghent 			*autoneg = TRUE;
51473cd555cSBin Tu - Sun Microsystems - Beijing China 	}
51573cd555cSBin Tu - Sun Microsystems - Beijing China 
51673cd555cSBin Tu - Sun Microsystems - Beijing China out:
51763b3bba8SJerry Jelinek 	return status;
51873cd555cSBin Tu - Sun Microsystems - Beijing China }
51973cd555cSBin Tu - Sun Microsystems - Beijing China 
52063b3bba8SJerry Jelinek /**
52163b3bba8SJerry Jelinek  *  ixgbe_get_media_type_82599 - Get media type
52263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
52373cd555cSBin Tu - Sun Microsystems - Beijing China  *
52463b3bba8SJerry Jelinek  *  Returns the media type (fiber, copper, backplane)
52563b3bba8SJerry Jelinek  **/
ixgbe_get_media_type_82599(struct ixgbe_hw * hw)52663b3bba8SJerry Jelinek enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
52773cd555cSBin Tu - Sun Microsystems - Beijing China {
52873cd555cSBin Tu - Sun Microsystems - Beijing China 	enum ixgbe_media_type media_type;
52973cd555cSBin Tu - Sun Microsystems - Beijing China 
5303cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_media_type_82599");
5313cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
53273cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Detect if there is a copper PHY attached. */
53363b3bba8SJerry Jelinek 	switch (hw->phy.type) {
53463b3bba8SJerry Jelinek 	case ixgbe_phy_cu_unknown:
53563b3bba8SJerry Jelinek 	case ixgbe_phy_tn:
53673cd555cSBin Tu - Sun Microsystems - Beijing China 		media_type = ixgbe_media_type_copper;
53773cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
53863b3bba8SJerry Jelinek 	default:
53963b3bba8SJerry Jelinek 		break;
54073cd555cSBin Tu - Sun Microsystems - Beijing China 	}
54173cd555cSBin Tu - Sun Microsystems - Beijing China 
54273cd555cSBin Tu - Sun Microsystems - Beijing China 	switch (hw->device_id) {
54373cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_DEV_ID_82599_KX4:
5443cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	case IXGBE_DEV_ID_82599_KX4_MEZZ:
5453cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
5460fa55b7aSRobert Mustacchi 	case IXGBE_DEV_ID_82599_KR:
54763b3bba8SJerry Jelinek 	case IXGBE_DEV_ID_82599_BACKPLANE_FCOE:
548185c5677SPaul Guo 	case IXGBE_DEV_ID_82599_XAUI_LOM:
54973cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Default device ID is mezzanine card KX/KX4 */
55073cd555cSBin Tu - Sun Microsystems - Beijing China 		media_type = ixgbe_media_type_backplane;
55173cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
55273cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_DEV_ID_82599_SFP:
55363b3bba8SJerry Jelinek 	case IXGBE_DEV_ID_82599_SFP_FCOE:
5540fa55b7aSRobert Mustacchi 	case IXGBE_DEV_ID_82599_SFP_EM:
5550fa55b7aSRobert Mustacchi 	case IXGBE_DEV_ID_82599_SFP_SF2:
556dc0cb1cdSDale Ghent 	case IXGBE_DEV_ID_82599_SFP_SF_QP:
5570fa55b7aSRobert Mustacchi 	case IXGBE_DEV_ID_82599EN_SFP:
55873cd555cSBin Tu - Sun Microsystems - Beijing China 		media_type = ixgbe_media_type_fiber;
55973cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
56073cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_DEV_ID_82599_CX4:
5613cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		media_type = ixgbe_media_type_cx4;
56273cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
5635b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	case IXGBE_DEV_ID_82599_T3_LOM:
56419843f01SPaul Guo 		media_type = ixgbe_media_type_copper;
56519843f01SPaul Guo 		break;
566dc0cb1cdSDale Ghent 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
567dc0cb1cdSDale Ghent 		media_type = ixgbe_media_type_fiber_qsfp;
568dc0cb1cdSDale Ghent 		break;
569dc0cb1cdSDale Ghent 	case IXGBE_DEV_ID_82599_BYPASS:
570dc0cb1cdSDale Ghent 		media_type = ixgbe_media_type_fiber_fixed;
571dc0cb1cdSDale Ghent 		hw->phy.multispeed_fiber = TRUE;
572dc0cb1cdSDale Ghent 		break;
57373cd555cSBin Tu - Sun Microsystems - Beijing China 	default:
57473cd555cSBin Tu - Sun Microsystems - Beijing China 		media_type = ixgbe_media_type_unknown;
57573cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
57673cd555cSBin Tu - Sun Microsystems - Beijing China 	}
57773cd555cSBin Tu - Sun Microsystems - Beijing China out:
57863b3bba8SJerry Jelinek 	return media_type;
57973cd555cSBin Tu - Sun Microsystems - Beijing China }
58073cd555cSBin Tu - Sun Microsystems - Beijing China 
581dc0cb1cdSDale Ghent /**
582dc0cb1cdSDale Ghent  *  ixgbe_stop_mac_link_on_d3_82599 - Disables link on D3
583dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
584dc0cb1cdSDale Ghent  *
585dc0cb1cdSDale Ghent  *  Disables link during D3 power down sequence.
586dc0cb1cdSDale Ghent  *
587dc0cb1cdSDale Ghent  **/
ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw * hw)588dc0cb1cdSDale Ghent void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw)
589dc0cb1cdSDale Ghent {
590dc0cb1cdSDale Ghent 	u32 autoc2_reg;
591dc0cb1cdSDale Ghent 	u16 ee_ctrl_2 = 0;
592dc0cb1cdSDale Ghent 
593dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_stop_mac_link_on_d3_82599");
594dc0cb1cdSDale Ghent 	ixgbe_read_eeprom(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2);
595dc0cb1cdSDale Ghent 
596dc0cb1cdSDale Ghent 	if (!ixgbe_mng_present(hw) && !hw->wol_enabled &&
597dc0cb1cdSDale Ghent 	    ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) {
598dc0cb1cdSDale Ghent 		autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
599dc0cb1cdSDale Ghent 		autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK;
600dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
601dc0cb1cdSDale Ghent 	}
602dc0cb1cdSDale Ghent }
603dc0cb1cdSDale Ghent 
60463b3bba8SJerry Jelinek /**
60563b3bba8SJerry Jelinek  *  ixgbe_start_mac_link_82599 - Setup MAC link settings
60663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
60763b3bba8SJerry Jelinek  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
60873cd555cSBin Tu - Sun Microsystems - Beijing China  *
60963b3bba8SJerry Jelinek  *  Configures link settings based on values in the ixgbe_hw struct.
61063b3bba8SJerry Jelinek  *  Restarts the link.  Performs autonegotiation if needed.
61163b3bba8SJerry Jelinek  **/
ixgbe_start_mac_link_82599(struct ixgbe_hw * hw,bool autoneg_wait_to_complete)61263b3bba8SJerry Jelinek s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
61369b5a878SDan McDonald 			       bool autoneg_wait_to_complete)
61473cd555cSBin Tu - Sun Microsystems - Beijing China {
61573cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 autoc_reg;
61673cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 links_reg;
61773cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 i;
61873cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 status = IXGBE_SUCCESS;
619dc0cb1cdSDale Ghent 	bool got_lock = FALSE;
62073cd555cSBin Tu - Sun Microsystems - Beijing China 
6213cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_start_mac_link_82599");
6223cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
62363b3bba8SJerry Jelinek 
624dc0cb1cdSDale Ghent 	/*  reset_pipeline requires us to hold this lock as it writes to
625dc0cb1cdSDale Ghent 	 *  AUTOC.
626dc0cb1cdSDale Ghent 	 */
627dc0cb1cdSDale Ghent 	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
628dc0cb1cdSDale Ghent 		status = hw->mac.ops.acquire_swfw_sync(hw,
629dc0cb1cdSDale Ghent 						       IXGBE_GSSR_MAC_CSR_SM);
630dc0cb1cdSDale Ghent 		if (status != IXGBE_SUCCESS)
631dc0cb1cdSDale Ghent 			goto out;
632dc0cb1cdSDale Ghent 
633dc0cb1cdSDale Ghent 		got_lock = TRUE;
634dc0cb1cdSDale Ghent 	}
635dc0cb1cdSDale Ghent 
63673cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Restart link */
637dc0cb1cdSDale Ghent 	ixgbe_reset_pipeline_82599(hw);
638dc0cb1cdSDale Ghent 
639dc0cb1cdSDale Ghent 	if (got_lock)
640dc0cb1cdSDale Ghent 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
64173cd555cSBin Tu - Sun Microsystems - Beijing China 
64273cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Only poll for autoneg to complete if specified to do so */
6433cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (autoneg_wait_to_complete) {
644dc0cb1cdSDale Ghent 		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
64573cd555cSBin Tu - Sun Microsystems - Beijing China 		if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
64663b3bba8SJerry Jelinek 		     IXGBE_AUTOC_LMS_KX4_KX_KR ||
64773cd555cSBin Tu - Sun Microsystems - Beijing China 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
64863b3bba8SJerry Jelinek 		     IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
64973cd555cSBin Tu - Sun Microsystems - Beijing China 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
65063b3bba8SJerry Jelinek 		     IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
65173cd555cSBin Tu - Sun Microsystems - Beijing China 			links_reg = 0; /* Just in case Autoneg time = 0 */
65273cd555cSBin Tu - Sun Microsystems - Beijing China 			for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
65373cd555cSBin Tu - Sun Microsystems - Beijing China 				links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
65473cd555cSBin Tu - Sun Microsystems - Beijing China 				if (links_reg & IXGBE_LINKS_KX_AN_COMP)
65573cd555cSBin Tu - Sun Microsystems - Beijing China 					break;
65673cd555cSBin Tu - Sun Microsystems - Beijing China 				msec_delay(100);
65773cd555cSBin Tu - Sun Microsystems - Beijing China 			}
65873cd555cSBin Tu - Sun Microsystems - Beijing China 			if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
65973cd555cSBin Tu - Sun Microsystems - Beijing China 				status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
66073cd555cSBin Tu - Sun Microsystems - Beijing China 				DEBUGOUT("Autoneg did not complete.\n");
66173cd555cSBin Tu - Sun Microsystems - Beijing China 			}
66273cd555cSBin Tu - Sun Microsystems - Beijing China 		}
66373cd555cSBin Tu - Sun Microsystems - Beijing China 	}
66473cd555cSBin Tu - Sun Microsystems - Beijing China 
66573cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Add delay to filter out noises during initial link setup */
66673cd555cSBin Tu - Sun Microsystems - Beijing China 	msec_delay(50);
66773cd555cSBin Tu - Sun Microsystems - Beijing China 
668dc0cb1cdSDale Ghent out:
66963b3bba8SJerry Jelinek 	return status;
67073cd555cSBin Tu - Sun Microsystems - Beijing China }
67173cd555cSBin Tu - Sun Microsystems - Beijing China 
67263b3bba8SJerry Jelinek /**
67363b3bba8SJerry Jelinek  *  ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
67463b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
6755b6dd21fSchenlu chen - Sun Microsystems - Beijing China  *
67663b3bba8SJerry Jelinek  *  The base drivers may require better control over SFP+ module
67763b3bba8SJerry Jelinek  *  PHY states.  This includes selectively shutting down the Tx
67863b3bba8SJerry Jelinek  *  laser on the PHY, effectively halting physical link.
67963b3bba8SJerry Jelinek  **/
ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)68063b3bba8SJerry Jelinek void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
6815b6dd21fSchenlu chen - Sun Microsystems - Beijing China {
6825b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
6835b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
684dc0cb1cdSDale Ghent 	/* Blocked by MNG FW so bail */
685dc0cb1cdSDale Ghent 	if (ixgbe_check_reset_blocked(hw))
686dc0cb1cdSDale Ghent 		return;
687dc0cb1cdSDale Ghent 
688dc0cb1cdSDale Ghent 	/* Disable Tx laser; allow 100us to go dark per spec */
6895b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	esdp_reg |= IXGBE_ESDP_SDP3;
6905b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
6915b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
6925b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	usec_delay(100);
6935b6dd21fSchenlu chen - Sun Microsystems - Beijing China }
6945b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
69563b3bba8SJerry Jelinek /**
69663b3bba8SJerry Jelinek  *  ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser
69763b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
6985b6dd21fSchenlu chen - Sun Microsystems - Beijing China  *
69963b3bba8SJerry Jelinek  *  The base drivers may require better control over SFP+ module
70063b3bba8SJerry Jelinek  *  PHY states.  This includes selectively turning on the Tx
70163b3bba8SJerry Jelinek  *  laser on the PHY, effectively starting physical link.
70263b3bba8SJerry Jelinek  **/
ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)70363b3bba8SJerry Jelinek void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
7045b6dd21fSchenlu chen - Sun Microsystems - Beijing China {
7055b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
7065b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
707dc0cb1cdSDale Ghent 	/* Enable Tx laser; allow 100ms to light up */
7085b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	esdp_reg &= ~IXGBE_ESDP_SDP3;
7095b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
7105b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
7115b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	msec_delay(100);
7125b6dd21fSchenlu chen - Sun Microsystems - Beijing China }
7135b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
71463b3bba8SJerry Jelinek /**
71563b3bba8SJerry Jelinek  *  ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
71663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
7175b6dd21fSchenlu chen - Sun Microsystems - Beijing China  *
71863b3bba8SJerry Jelinek  *  When the driver changes the link speeds that it can support,
71963b3bba8SJerry Jelinek  *  it sets autotry_restart to TRUE to indicate that we need to
72063b3bba8SJerry Jelinek  *  initiate a new autotry session with the link partner.  To do
721dc0cb1cdSDale Ghent  *  so, we set the speed then disable and re-enable the Tx laser, to
72263b3bba8SJerry Jelinek  *  alert the link partner that it also needs to restart autotry on its
72363b3bba8SJerry Jelinek  *  end.  This is consistent with TRUE clause 37 autoneg, which also
72463b3bba8SJerry Jelinek  *  involves a loss of signal.
72563b3bba8SJerry Jelinek  **/
ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)72663b3bba8SJerry Jelinek void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
7275b6dd21fSchenlu chen - Sun Microsystems - Beijing China {
7285b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber");
7295b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
730dc0cb1cdSDale Ghent 	/* Blocked by MNG FW so bail */
731dc0cb1cdSDale Ghent 	if (ixgbe_check_reset_blocked(hw))
732dc0cb1cdSDale Ghent 		return;
733dc0cb1cdSDale Ghent 
7345b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (hw->mac.autotry_restart) {
7355b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		ixgbe_disable_tx_laser_multispeed_fiber(hw);
7365b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		ixgbe_enable_tx_laser_multispeed_fiber(hw);
73763b3bba8SJerry Jelinek 		hw->mac.autotry_restart = FALSE;
7385b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	}
7395b6dd21fSchenlu chen - Sun Microsystems - Beijing China }
7405b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
74163b3bba8SJerry Jelinek /**
742dc0cb1cdSDale Ghent  *  ixgbe_set_hard_rate_select_speed - Set module link speed
74363b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
744dc0cb1cdSDale Ghent  *  @speed: link speed to set
74573cd555cSBin Tu - Sun Microsystems - Beijing China  *
746dc0cb1cdSDale Ghent  *  Set module link speed via RS0/RS1 rate select pins.
747dc0cb1cdSDale Ghent  */
ixgbe_set_hard_rate_select_speed(struct ixgbe_hw * hw,ixgbe_link_speed speed)748dc0cb1cdSDale Ghent void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw,
749dc0cb1cdSDale Ghent 					ixgbe_link_speed speed)
75073cd555cSBin Tu - Sun Microsystems - Beijing China {
75173cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
75273cd555cSBin Tu - Sun Microsystems - Beijing China 
753dc0cb1cdSDale Ghent 	switch (speed) {
754dc0cb1cdSDale Ghent 	case IXGBE_LINK_SPEED_10GB_FULL:
75573cd555cSBin Tu - Sun Microsystems - Beijing China 		esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
756dc0cb1cdSDale Ghent 		break;
757dc0cb1cdSDale Ghent 	case IXGBE_LINK_SPEED_1GB_FULL:
75873cd555cSBin Tu - Sun Microsystems - Beijing China 		esdp_reg &= ~IXGBE_ESDP_SDP5;
75973cd555cSBin Tu - Sun Microsystems - Beijing China 		esdp_reg |= IXGBE_ESDP_SDP5_DIR;
760dc0cb1cdSDale Ghent 		break;
761dc0cb1cdSDale Ghent 	default:
762dc0cb1cdSDale Ghent 		DEBUGOUT("Invalid fixed module speed\n");
763dc0cb1cdSDale Ghent 		return;
76473cd555cSBin Tu - Sun Microsystems - Beijing China 	}
76573cd555cSBin Tu - Sun Microsystems - Beijing China 
766dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
767dc0cb1cdSDale Ghent 	IXGBE_WRITE_FLUSH(hw);
76873cd555cSBin Tu - Sun Microsystems - Beijing China }
76973cd555cSBin Tu - Sun Microsystems - Beijing China 
77063b3bba8SJerry Jelinek /**
77163b3bba8SJerry Jelinek  *  ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed
77263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
77363b3bba8SJerry Jelinek  *  @speed: new link speed
77463b3bba8SJerry Jelinek  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
77573cd555cSBin Tu - Sun Microsystems - Beijing China  *
77663b3bba8SJerry Jelinek  *  Implements the Intel SmartSpeed algorithm.
77763b3bba8SJerry Jelinek  **/
ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)77863b3bba8SJerry Jelinek s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
779dc0cb1cdSDale Ghent 				    ixgbe_link_speed speed,
78069b5a878SDan McDonald 				    bool autoneg_wait_to_complete)
78173cd555cSBin Tu - Sun Microsystems - Beijing China {
7823cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	s32 status = IXGBE_SUCCESS;
7835b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
7843cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	s32 i, j;
78563b3bba8SJerry Jelinek 	bool link_up = FALSE;
7863cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
78773cd555cSBin Tu - Sun Microsystems - Beijing China 
7883cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_setup_mac_link_smartspeed");
7893cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
79063b3bba8SJerry Jelinek 	 /* Set autoneg_advertised value based on input link speed */
7913cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	hw->phy.autoneg_advertised = 0;
7923cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
7933cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
7943cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
7953cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
7963cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
7973cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
7983cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
7993cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (speed & IXGBE_LINK_SPEED_100_FULL)
8003cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
8013cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8023cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
8033cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * Implement Intel SmartSpeed algorithm.  SmartSpeed will reduce the
8043cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * autoneg advertisement if link is unable to be established at the
8053cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * highest negotiated rate.  This can sometimes happen due to integrity
8063cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * issues with the physical media connection.
8073cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
8083cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8093cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* First, try to get link with full advertisement */
81063b3bba8SJerry Jelinek 	hw->phy.smart_speed_active = FALSE;
8113cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) {
812dc0cb1cdSDale Ghent 		status = ixgbe_setup_mac_link_82599(hw, speed,
81363b3bba8SJerry Jelinek 						    autoneg_wait_to_complete);
8143cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		if (status != IXGBE_SUCCESS)
8153cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			goto out;
8163cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8173cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		/*
8183cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		 * Wait for the controller to acquire link.  Per IEEE 802.3ap,
8193cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		 * Section 73.10.2, we may have to wait up to 500ms if KR is
8203cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		 * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per
8213cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		 * Table 9 in the AN MAS.
8223cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		 */
8233cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		for (i = 0; i < 5; i++) {
82473cd555cSBin Tu - Sun Microsystems - Beijing China 			msec_delay(100);
8253cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8263cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			/* If we have link, just jump out */
8273cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			status = ixgbe_check_link(hw, &link_speed, &link_up,
82863b3bba8SJerry Jelinek 						  FALSE);
8293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			if (status != IXGBE_SUCCESS)
8303cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 				goto out;
8313cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8323cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			if (link_up)
8333cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 				goto out;
83473cd555cSBin Tu - Sun Microsystems - Beijing China 		}
83573cd555cSBin Tu - Sun Microsystems - Beijing China 	}
83673cd555cSBin Tu - Sun Microsystems - Beijing China 
8373cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
8383cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * We didn't get link.  If we advertised KR plus one of KX4/KX
8393cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * (or BX4/BX), then disable KR and try again.
8403cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
8413cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) ||
8423cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	    ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0))
8433cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		goto out;
8443cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8453cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* Turn SmartSpeed on to disable KR support */
84663b3bba8SJerry Jelinek 	hw->phy.smart_speed_active = TRUE;
847dc0cb1cdSDale Ghent 	status = ixgbe_setup_mac_link_82599(hw, speed,
84863b3bba8SJerry Jelinek 					    autoneg_wait_to_complete);
8493cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (status != IXGBE_SUCCESS)
8503cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		goto out;
8513cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8523cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
8533cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * Wait for the controller to acquire link.  600ms will allow for
8543cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * the AN link_fail_inhibit_timer as well for multiple cycles of
8553cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * parallel detect, both 10g and 1g. This allows for the maximum
8563cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * connect attempts as defined in the AN MAS table 73-7.
8573cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
8583cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (i = 0; i < 6; i++) {
8593cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		msec_delay(100);
8603cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8613cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		/* If we have link, just jump out */
86263b3bba8SJerry Jelinek 		status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
8633cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		if (status != IXGBE_SUCCESS)
8643cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			goto out;
86573cd555cSBin Tu - Sun Microsystems - Beijing China 
8663cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		if (link_up)
8673cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			goto out;
86873cd555cSBin Tu - Sun Microsystems - Beijing China 	}
86973cd555cSBin Tu - Sun Microsystems - Beijing China 
8703cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* We didn't get link.  Turn SmartSpeed back off. */
87163b3bba8SJerry Jelinek 	hw->phy.smart_speed_active = FALSE;
872dc0cb1cdSDale Ghent 	status = ixgbe_setup_mac_link_82599(hw, speed,
87363b3bba8SJerry Jelinek 					    autoneg_wait_to_complete);
8743cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
8753cfa0eb9Schenlu chen - Sun Microsystems - Beijing China out:
8765b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
8775b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		DEBUGOUT("Smartspeed has downgraded the link speed "
8785b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		"from the maximum advertised\n");
87963b3bba8SJerry Jelinek 	return status;
88073cd555cSBin Tu - Sun Microsystems - Beijing China }
88173cd555cSBin Tu - Sun Microsystems - Beijing China 
88263b3bba8SJerry Jelinek /**
88363b3bba8SJerry Jelinek  *  ixgbe_setup_mac_link_82599 - Set MAC link speed
88463b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
88563b3bba8SJerry Jelinek  *  @speed: new link speed
88663b3bba8SJerry Jelinek  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
88773cd555cSBin Tu - Sun Microsystems - Beijing China  *
88863b3bba8SJerry Jelinek  *  Set the link speed in the AUTOC register and restarts link.
88963b3bba8SJerry Jelinek  **/
ixgbe_setup_mac_link_82599(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)89063b3bba8SJerry Jelinek s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
891dc0cb1cdSDale Ghent 			       ixgbe_link_speed speed,
89269b5a878SDan McDonald 			       bool autoneg_wait_to_complete)
89373cd555cSBin Tu - Sun Microsystems - Beijing China {
894dc0cb1cdSDale Ghent 	bool autoneg = FALSE;
89573cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 status = IXGBE_SUCCESS;
896dc0cb1cdSDale Ghent 	u32 pma_pmd_1g, link_mode;
897dc0cb1cdSDale Ghent 	u32 current_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); /* holds the value of AUTOC register at this current point in time */
898dc0cb1cdSDale Ghent 	u32 orig_autoc = 0; /* holds the cached value of AUTOC register */
899dc0cb1cdSDale Ghent 	u32 autoc = current_autoc; /* Temporary variable used for comparison purposes */
90073cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
90173cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
90273cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 links_reg;
90373cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 i;
90473cd555cSBin Tu - Sun Microsystems - Beijing China 	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
90573cd555cSBin Tu - Sun Microsystems - Beijing China 
9063cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_setup_mac_link_82599");
9073cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
90873cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Check to see if speed passed in is supported. */
90973cd555cSBin Tu - Sun Microsystems - Beijing China 	status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg);
910dc0cb1cdSDale Ghent 	if (status)
91173cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
91273cd555cSBin Tu - Sun Microsystems - Beijing China 
91373cd555cSBin Tu - Sun Microsystems - Beijing China 	speed &= link_capabilities;
91473cd555cSBin Tu - Sun Microsystems - Beijing China 
91573cd555cSBin Tu - Sun Microsystems - Beijing China 	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
91673cd555cSBin Tu - Sun Microsystems - Beijing China 		status = IXGBE_ERR_LINK_SETUP;
917185c5677SPaul Guo 		goto out;
918185c5677SPaul Guo 	}
919185c5677SPaul Guo 
92063b3bba8SJerry Jelinek 	/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
921185c5677SPaul Guo 	if (hw->mac.orig_link_settings_stored)
922185c5677SPaul Guo 		orig_autoc = hw->mac.orig_autoc;
923185c5677SPaul Guo 	else
924185c5677SPaul Guo 		orig_autoc = autoc;
925185c5677SPaul Guo 
926dc0cb1cdSDale Ghent 	link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
927dc0cb1cdSDale Ghent 	pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
928dc0cb1cdSDale Ghent 
929185c5677SPaul Guo 	if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
93073cd555cSBin Tu - Sun Microsystems - Beijing China 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
93173cd555cSBin Tu - Sun Microsystems - Beijing China 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
93273cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Set KX4/KX/KR support according to speed requested */
93373cd555cSBin Tu - Sun Microsystems - Beijing China 		autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP);
934b44bad03SDan McDonald 		if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
935185c5677SPaul Guo 			if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)
93673cd555cSBin Tu - Sun Microsystems - Beijing China 				autoc |= IXGBE_AUTOC_KX4_SUPP;
9373cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) &&
93863b3bba8SJerry Jelinek 			    (hw->phy.smart_speed_active == FALSE))
93973cd555cSBin Tu - Sun Microsystems - Beijing China 				autoc |= IXGBE_AUTOC_KR_SUPP;
940b44bad03SDan McDonald 		}
94173cd555cSBin Tu - Sun Microsystems - Beijing China 		if (speed & IXGBE_LINK_SPEED_1GB_FULL)
94273cd555cSBin Tu - Sun Microsystems - Beijing China 			autoc |= IXGBE_AUTOC_KX_SUPP;
94373cd555cSBin Tu - Sun Microsystems - Beijing China 	} else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) &&
94469b5a878SDan McDonald 		   (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN ||
94569b5a878SDan McDonald 		    link_mode == IXGBE_AUTOC_LMS_1G_AN)) {
94673cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Switch from 1G SFI to 10G SFI if requested */
94773cd555cSBin Tu - Sun Microsystems - Beijing China 		if ((speed == IXGBE_LINK_SPEED_10GB_FULL) &&
94873cd555cSBin Tu - Sun Microsystems - Beijing China 		    (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) {
94973cd555cSBin Tu - Sun Microsystems - Beijing China 			autoc &= ~IXGBE_AUTOC_LMS_MASK;
95073cd555cSBin Tu - Sun Microsystems - Beijing China 			autoc |= IXGBE_AUTOC_LMS_10G_SERIAL;
95173cd555cSBin Tu - Sun Microsystems - Beijing China 		}
95273cd555cSBin Tu - Sun Microsystems - Beijing China 	} else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) &&
95369b5a878SDan McDonald 		   (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) {
95473cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Switch from 10G SFI to 1G SFI if requested */
95573cd555cSBin Tu - Sun Microsystems - Beijing China 		if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
95673cd555cSBin Tu - Sun Microsystems - Beijing China 		    (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) {
95773cd555cSBin Tu - Sun Microsystems - Beijing China 			autoc &= ~IXGBE_AUTOC_LMS_MASK;
958dc0cb1cdSDale Ghent 			if (autoneg || hw->phy.type == ixgbe_phy_qsfp_intel)
95973cd555cSBin Tu - Sun Microsystems - Beijing China 				autoc |= IXGBE_AUTOC_LMS_1G_AN;
96073cd555cSBin Tu - Sun Microsystems - Beijing China 			else
96173cd555cSBin Tu - Sun Microsystems - Beijing China 				autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
96263b3bba8SJerry Jelinek 		}
96373cd555cSBin Tu - Sun Microsystems - Beijing China 	}
96473cd555cSBin Tu - Sun Microsystems - Beijing China 
965dc0cb1cdSDale Ghent 	if (autoc != current_autoc) {
96673cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Restart link */
967dc0cb1cdSDale Ghent 		status = hw->mac.ops.prot_autoc_write(hw, autoc, FALSE);
968dc0cb1cdSDale Ghent 		if (status != IXGBE_SUCCESS)
969dc0cb1cdSDale Ghent 			goto out;
97073cd555cSBin Tu - Sun Microsystems - Beijing China 
97173cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Only poll for autoneg to complete if specified to do so */
97273cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoneg_wait_to_complete) {
97373cd555cSBin Tu - Sun Microsystems - Beijing China 			if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
97473cd555cSBin Tu - Sun Microsystems - Beijing China 			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
97573cd555cSBin Tu - Sun Microsystems - Beijing China 			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
97663b3bba8SJerry Jelinek 				links_reg = 0; /*Just in case Autoneg time=0*/
97773cd555cSBin Tu - Sun Microsystems - Beijing China 				for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
97873cd555cSBin Tu - Sun Microsystems - Beijing China 					links_reg =
97963b3bba8SJerry Jelinek 					       IXGBE_READ_REG(hw, IXGBE_LINKS);
98073cd555cSBin Tu - Sun Microsystems - Beijing China 					if (links_reg & IXGBE_LINKS_KX_AN_COMP)
98173cd555cSBin Tu - Sun Microsystems - Beijing China 						break;
98273cd555cSBin Tu - Sun Microsystems - Beijing China 					msec_delay(100);
98373cd555cSBin Tu - Sun Microsystems - Beijing China 				}
98473cd555cSBin Tu - Sun Microsystems - Beijing China 				if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
98573cd555cSBin Tu - Sun Microsystems - Beijing China 					status =
98663b3bba8SJerry Jelinek 						IXGBE_ERR_AUTONEG_NOT_COMPLETE;
98773cd555cSBin Tu - Sun Microsystems - Beijing China 					DEBUGOUT("Autoneg did not complete.\n");
98873cd555cSBin Tu - Sun Microsystems - Beijing China 				}
98973cd555cSBin Tu - Sun Microsystems - Beijing China 			}
99073cd555cSBin Tu - Sun Microsystems - Beijing China 		}
99173cd555cSBin Tu - Sun Microsystems - Beijing China 
99273cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Add delay to filter out noises during initial link setup */
99373cd555cSBin Tu - Sun Microsystems - Beijing China 		msec_delay(50);
99473cd555cSBin Tu - Sun Microsystems - Beijing China 	}
99573cd555cSBin Tu - Sun Microsystems - Beijing China 
99673cd555cSBin Tu - Sun Microsystems - Beijing China out:
99763b3bba8SJerry Jelinek 	return status;
99873cd555cSBin Tu - Sun Microsystems - Beijing China }
99973cd555cSBin Tu - Sun Microsystems - Beijing China 
100063b3bba8SJerry Jelinek /**
100163b3bba8SJerry Jelinek  *  ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field
100263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
100363b3bba8SJerry Jelinek  *  @speed: new link speed
100463b3bba8SJerry Jelinek  *  @autoneg_wait_to_complete: TRUE if waiting is needed to complete
100573cd555cSBin Tu - Sun Microsystems - Beijing China  *
100663b3bba8SJerry Jelinek  *  Restarts link on PHY and MAC based on settings passed in.
100763b3bba8SJerry Jelinek  **/
ixgbe_setup_copper_link_82599(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)100863b3bba8SJerry Jelinek static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
100969b5a878SDan McDonald 					 ixgbe_link_speed speed,
101069b5a878SDan McDonald 					 bool autoneg_wait_to_complete)
101173cd555cSBin Tu - Sun Microsystems - Beijing China {
101273cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 status;
101373cd555cSBin Tu - Sun Microsystems - Beijing China 
10143cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_setup_copper_link_82599");
10153cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
101673cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Setup the PHY according to input speed */
1017dc0cb1cdSDale Ghent 	status = hw->phy.ops.setup_link_speed(hw, speed,
101869b5a878SDan McDonald 					      autoneg_wait_to_complete);
1019dc0cb1cdSDale Ghent 	/* Set up MAC */
1020dc0cb1cdSDale Ghent 	ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete);
102173cd555cSBin Tu - Sun Microsystems - Beijing China 
102263b3bba8SJerry Jelinek 	return status;
102373cd555cSBin Tu - Sun Microsystems - Beijing China }
102463b3bba8SJerry Jelinek 
102563b3bba8SJerry Jelinek /**
102663b3bba8SJerry Jelinek  *  ixgbe_reset_hw_82599 - Perform hardware reset
102763b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
102873cd555cSBin Tu - Sun Microsystems - Beijing China  *
102963b3bba8SJerry Jelinek  *  Resets the hardware by resetting the transmit and receive units, masks
103063b3bba8SJerry Jelinek  *  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
103163b3bba8SJerry Jelinek  *  reset.
103263b3bba8SJerry Jelinek  **/
ixgbe_reset_hw_82599(struct ixgbe_hw * hw)103363b3bba8SJerry Jelinek s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
103473cd555cSBin Tu - Sun Microsystems - Beijing China {
103569b5a878SDan McDonald 	ixgbe_link_speed link_speed;
103669b5a878SDan McDonald 	s32 status;
1037dc0cb1cdSDale Ghent 	u32 ctrl = 0;
1038dc0cb1cdSDale Ghent 	u32 i, autoc, autoc2;
1039dc0cb1cdSDale Ghent 	u32 curr_lms;
104069b5a878SDan McDonald 	bool link_up = FALSE;
104173cd555cSBin Tu - Sun Microsystems - Beijing China 
10423cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_reset_hw_82599");
10433cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
104473cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Call adapter stop to disable tx/rx and clear interrupts */
104569b5a878SDan McDonald 	status = hw->mac.ops.stop_adapter(hw);
104669b5a878SDan McDonald 	if (status != IXGBE_SUCCESS)
104769b5a878SDan McDonald 		goto reset_hw_out;
104869b5a878SDan McDonald 
104969b5a878SDan McDonald 	/* flush pending Tx transactions */
105069b5a878SDan McDonald 	ixgbe_clear_tx_pending(hw);
105173cd555cSBin Tu - Sun Microsystems - Beijing China 
105273cd555cSBin Tu - Sun Microsystems - Beijing China 	/* PHY ops must be identified and initialized prior to reset */
105373cd555cSBin Tu - Sun Microsystems - Beijing China 
105473cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Identify PHY and related function pointers */
105573cd555cSBin Tu - Sun Microsystems - Beijing China 	status = hw->phy.ops.init(hw);
105673cd555cSBin Tu - Sun Microsystems - Beijing China 
1057185c5677SPaul Guo 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
1058185c5677SPaul Guo 		goto reset_hw_out;
1059185c5677SPaul Guo 
106073cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Setup SFP module if there is one present. */
106173cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->phy.sfp_setup_needed) {
106273cd555cSBin Tu - Sun Microsystems - Beijing China 		status = hw->mac.ops.setup_sfp(hw);
106363b3bba8SJerry Jelinek 		hw->phy.sfp_setup_needed = FALSE;
106473cd555cSBin Tu - Sun Microsystems - Beijing China 	}
106573cd555cSBin Tu - Sun Microsystems - Beijing China 
1066185c5677SPaul Guo 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
1067185c5677SPaul Guo 		goto reset_hw_out;
1068185c5677SPaul Guo 
106973cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Reset PHY */
107063b3bba8SJerry Jelinek 	if (hw->phy.reset_disable == FALSE && hw->phy.ops.reset != NULL)
107173cd555cSBin Tu - Sun Microsystems - Beijing China 		hw->phy.ops.reset(hw);
107273cd555cSBin Tu - Sun Microsystems - Beijing China 
1073dc0cb1cdSDale Ghent 	/* remember AUTOC from before we reset */
1074dc0cb1cdSDale Ghent 	curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
1075dc0cb1cdSDale Ghent 
107619843f01SPaul Guo mac_reset_top:
107773cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
107869b5a878SDan McDonald 	 * Issue global reset to the MAC.  Needs to be SW reset if link is up.
107969b5a878SDan McDonald 	 * If link reset is used when link is up, it might reset the PHY when
108069b5a878SDan McDonald 	 * mng is using it.  If link is down or the flag to force full link
108169b5a878SDan McDonald 	 * reset is set, then perform link reset.
108273cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
108369b5a878SDan McDonald 	ctrl = IXGBE_CTRL_LNK_RST;
108469b5a878SDan McDonald 	if (!hw->force_full_reset) {
108569b5a878SDan McDonald 		hw->mac.ops.check_link(hw, &link_speed, &link_up, FALSE);
108669b5a878SDan McDonald 		if (link_up)
108769b5a878SDan McDonald 			ctrl = IXGBE_CTRL_RST;
108869b5a878SDan McDonald 	}
108969b5a878SDan McDonald 
109069b5a878SDan McDonald 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
109169b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
109273cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
109373cd555cSBin Tu - Sun Microsystems - Beijing China 
1094dc0cb1cdSDale Ghent 	/* Poll for reset bit to self-clear meaning reset is complete */
109573cd555cSBin Tu - Sun Microsystems - Beijing China 	for (i = 0; i < 10; i++) {
109673cd555cSBin Tu - Sun Microsystems - Beijing China 		usec_delay(1);
109773cd555cSBin Tu - Sun Microsystems - Beijing China 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
109869b5a878SDan McDonald 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
109973cd555cSBin Tu - Sun Microsystems - Beijing China 			break;
110073cd555cSBin Tu - Sun Microsystems - Beijing China 	}
110169b5a878SDan McDonald 
110269b5a878SDan McDonald 	if (ctrl & IXGBE_CTRL_RST_MASK) {
110373cd555cSBin Tu - Sun Microsystems - Beijing China 		status = IXGBE_ERR_RESET_FAILED;
110473cd555cSBin Tu - Sun Microsystems - Beijing China 		DEBUGOUT("Reset polling failed to complete.\n");
110573cd555cSBin Tu - Sun Microsystems - Beijing China 	}
110673cd555cSBin Tu - Sun Microsystems - Beijing China 
110769b5a878SDan McDonald 	msec_delay(50);
110869b5a878SDan McDonald 
110919843f01SPaul Guo 	/*
111019843f01SPaul Guo 	 * Double resets are required for recovery from certain error
1111dc0cb1cdSDale Ghent 	 * conditions.  Between resets, it is necessary to stall to
1112dc0cb1cdSDale Ghent 	 * allow time for any pending HW events to complete.
111319843f01SPaul Guo 	 */
111419843f01SPaul Guo 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
111519843f01SPaul Guo 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
111619843f01SPaul Guo 		goto mac_reset_top;
111719843f01SPaul Guo 	}
111819843f01SPaul Guo 
111973cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
112073cd555cSBin Tu - Sun Microsystems - Beijing China 	 * Store the original AUTOC/AUTOC2 values if they have not been
112173cd555cSBin Tu - Sun Microsystems - Beijing China 	 * stored off yet.  Otherwise restore the stored original
112273cd555cSBin Tu - Sun Microsystems - Beijing China 	 * values since the reset operation sets back to defaults.
112373cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
112473cd555cSBin Tu - Sun Microsystems - Beijing China 	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
112573cd555cSBin Tu - Sun Microsystems - Beijing China 	autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
1126dc0cb1cdSDale Ghent 
1127dc0cb1cdSDale Ghent 	/* Enable link if disabled in NVM */
1128dc0cb1cdSDale Ghent 	if (autoc2 & IXGBE_AUTOC2_LINK_DISABLE_MASK) {
1129dc0cb1cdSDale Ghent 		autoc2 &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK;
1130dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
1131dc0cb1cdSDale Ghent 		IXGBE_WRITE_FLUSH(hw);
1132dc0cb1cdSDale Ghent 	}
1133dc0cb1cdSDale Ghent 
113463b3bba8SJerry Jelinek 	if (hw->mac.orig_link_settings_stored == FALSE) {
113573cd555cSBin Tu - Sun Microsystems - Beijing China 		hw->mac.orig_autoc = autoc;
113673cd555cSBin Tu - Sun Microsystems - Beijing China 		hw->mac.orig_autoc2 = autoc2;
113763b3bba8SJerry Jelinek 		hw->mac.orig_link_settings_stored = TRUE;
113873cd555cSBin Tu - Sun Microsystems - Beijing China 	} else {
1139dc0cb1cdSDale Ghent 
1140dc0cb1cdSDale Ghent 		/* If MNG FW is running on a multi-speed device that
1141dc0cb1cdSDale Ghent 		 * doesn't autoneg with out driver support we need to
1142dc0cb1cdSDale Ghent 		 * leave LMS in the state it was before we MAC reset.
1143dc0cb1cdSDale Ghent 		 * Likewise if we support WoL we don't want change the
1144dc0cb1cdSDale Ghent 		 * LMS state.
1145dc0cb1cdSDale Ghent 		 */
1146dc0cb1cdSDale Ghent 		if ((hw->phy.multispeed_fiber && ixgbe_mng_enabled(hw)) ||
1147dc0cb1cdSDale Ghent 		    hw->wol_enabled)
1148dc0cb1cdSDale Ghent 			hw->mac.orig_autoc =
1149dc0cb1cdSDale Ghent 				(hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
1150dc0cb1cdSDale Ghent 				curr_lms;
1151dc0cb1cdSDale Ghent 
1152dc0cb1cdSDale Ghent 		if (autoc != hw->mac.orig_autoc) {
1153dc0cb1cdSDale Ghent 			status = hw->mac.ops.prot_autoc_write(hw,
1154dc0cb1cdSDale Ghent 							hw->mac.orig_autoc,
1155dc0cb1cdSDale Ghent 							FALSE);
1156dc0cb1cdSDale Ghent 			if (status != IXGBE_SUCCESS)
1157dc0cb1cdSDale Ghent 				goto reset_hw_out;
1158dc0cb1cdSDale Ghent 		}
115973cd555cSBin Tu - Sun Microsystems - Beijing China 
116073cd555cSBin Tu - Sun Microsystems - Beijing China 		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
116173cd555cSBin Tu - Sun Microsystems - Beijing China 		    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
116273cd555cSBin Tu - Sun Microsystems - Beijing China 			autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
116373cd555cSBin Tu - Sun Microsystems - Beijing China 			autoc2 |= (hw->mac.orig_autoc2 &
116469b5a878SDan McDonald 				   IXGBE_AUTOC2_UPPER_MASK);
116573cd555cSBin Tu - Sun Microsystems - Beijing China 			IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
116673cd555cSBin Tu - Sun Microsystems - Beijing China 		}
116773cd555cSBin Tu - Sun Microsystems - Beijing China 	}
116873cd555cSBin Tu - Sun Microsystems - Beijing China 
1169185c5677SPaul Guo 	/* Store the permanent mac address */
1170185c5677SPaul Guo 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
1171185c5677SPaul Guo 
117273cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
117373cd555cSBin Tu - Sun Microsystems - Beijing China 	 * Store MAC address from RAR0, clear receive address registers, and
117473cd555cSBin Tu - Sun Microsystems - Beijing China 	 * clear the multicast table.  Also reset num_rar_entries to 128,
117573cd555cSBin Tu - Sun Microsystems - Beijing China 	 * since we modify this value when programming the SAN MAC address.
117673cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
117773cd555cSBin Tu - Sun Microsystems - Beijing China 	hw->mac.num_rar_entries = 128;
117873cd555cSBin Tu - Sun Microsystems - Beijing China 	hw->mac.ops.init_rx_addrs(hw);
117973cd555cSBin Tu - Sun Microsystems - Beijing China 
1180185c5677SPaul Guo 	/* Store the permanent SAN mac address */
1181185c5677SPaul Guo 	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
118273cd555cSBin Tu - Sun Microsystems - Beijing China 
118373cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Add the SAN MAC address to the RAR only if it's a valid address */
118473cd555cSBin Tu - Sun Microsystems - Beijing China 	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
118569b5a878SDan McDonald 		/* Save the SAN MAC RAR index */
118669b5a878SDan McDonald 		hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
118773cd555cSBin Tu - Sun Microsystems - Beijing China 
1188*48ed61a7SRobert Mustacchi 		hw->mac.ops.set_rar(hw, hw->mac.san_mac_rar_index,
1189*48ed61a7SRobert Mustacchi 				    hw->mac.san_addr, 0, IXGBE_RAH_AV);
1190*48ed61a7SRobert Mustacchi 
1191*48ed61a7SRobert Mustacchi 		/* clear VMDq pool/queue selection for this RAR */
1192*48ed61a7SRobert Mustacchi 		hw->mac.ops.clear_vmdq(hw, hw->mac.san_mac_rar_index,
1193*48ed61a7SRobert Mustacchi 				       IXGBE_CLEAR_VMDQ_ALL);
1194*48ed61a7SRobert Mustacchi 
119573cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Reserve the last RAR for the SAN MAC address */
119673cd555cSBin Tu - Sun Microsystems - Beijing China 		hw->mac.num_rar_entries--;
119773cd555cSBin Tu - Sun Microsystems - Beijing China 	}
119873cd555cSBin Tu - Sun Microsystems - Beijing China 
11993cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* Store the alternative WWNN/WWPN prefix */
12003cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
120169b5a878SDan McDonald 				   &hw->mac.wwpn_prefix);
12023cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
1203185c5677SPaul Guo reset_hw_out:
120463b3bba8SJerry Jelinek 	return status;
120573cd555cSBin Tu - Sun Microsystems - Beijing China }
120673cd555cSBin Tu - Sun Microsystems - Beijing China 
1207dc0cb1cdSDale Ghent /**
1208dc0cb1cdSDale Ghent  * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete
1209dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
1210dc0cb1cdSDale Ghent  * @fdircmd: current value of FDIRCMD register
1211dc0cb1cdSDale Ghent  */
ixgbe_fdir_check_cmd_complete(struct ixgbe_hw * hw,u32 * fdircmd)1212dc0cb1cdSDale Ghent static s32 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, u32 *fdircmd)
1213dc0cb1cdSDale Ghent {
1214dc0cb1cdSDale Ghent 	int i;
1215dc0cb1cdSDale Ghent 
1216dc0cb1cdSDale Ghent 	for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
1217dc0cb1cdSDale Ghent 		*fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
1218dc0cb1cdSDale Ghent 		if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK))
1219dc0cb1cdSDale Ghent 			return IXGBE_SUCCESS;
1220dc0cb1cdSDale Ghent 		usec_delay(10);
1221dc0cb1cdSDale Ghent 	}
1222dc0cb1cdSDale Ghent 
1223dc0cb1cdSDale Ghent 	return IXGBE_ERR_FDIR_CMD_INCOMPLETE;
1224dc0cb1cdSDale Ghent }
1225dc0cb1cdSDale Ghent 
122663b3bba8SJerry Jelinek /**
122763b3bba8SJerry Jelinek  *  ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
122863b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
122963b3bba8SJerry Jelinek  **/
ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw * hw)123063b3bba8SJerry Jelinek s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
123173cd555cSBin Tu - Sun Microsystems - Beijing China {
1232dc0cb1cdSDale Ghent 	s32 err;
1233185c5677SPaul Guo 	int i;
123473cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
1235dc0cb1cdSDale Ghent 	u32 fdircmd;
123673cd555cSBin Tu - Sun Microsystems - Beijing China 	fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
1237185c5677SPaul Guo 
12383cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_reinit_fdir_tables_82599");
12393cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
1240185c5677SPaul Guo 	/*
1241185c5677SPaul Guo 	 * Before starting reinitialization process,
1242185c5677SPaul Guo 	 * FDIRCMD.CMD must be zero.
1243185c5677SPaul Guo 	 */
1244dc0cb1cdSDale Ghent 	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
1245dc0cb1cdSDale Ghent 	if (err) {
1246dc0cb1cdSDale Ghent 		DEBUGOUT("Flow Director previous command did not complete, aborting table re-initialization.\n");
1247dc0cb1cdSDale Ghent 		return err;
1248185c5677SPaul Guo 	}
1249185c5677SPaul Guo 
125073cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
125173cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
1252185c5677SPaul Guo 	/*
1253185c5677SPaul Guo 	 * 82599 adapters flow director init flow cannot be restarted,
1254185c5677SPaul Guo 	 * Workaround 82599 silicon errata by performing the following steps
1255185c5677SPaul Guo 	 * before re-writing the FDIRCTRL control register with the same value.
1256185c5677SPaul Guo 	 * - write 1 to bit 8 of FDIRCMD register &
1257185c5677SPaul Guo 	 * - write 0 to bit 8 of FDIRCMD register
1258185c5677SPaul Guo 	 */
1259185c5677SPaul Guo 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
126069b5a878SDan McDonald 			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
126169b5a878SDan McDonald 			 IXGBE_FDIRCMD_CLEARHT));
1262185c5677SPaul Guo 	IXGBE_WRITE_FLUSH(hw);
1263185c5677SPaul Guo 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
126469b5a878SDan McDonald 			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
126569b5a878SDan McDonald 			 ~IXGBE_FDIRCMD_CLEARHT));
1266185c5677SPaul Guo 	IXGBE_WRITE_FLUSH(hw);
1267185c5677SPaul Guo 	/*
1268185c5677SPaul Guo 	 * Clear FDIR Hash register to clear any leftover hashes
1269185c5677SPaul Guo 	 * waiting to be programmed.
1270185c5677SPaul Guo 	 */
1271185c5677SPaul Guo 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00);
1272185c5677SPaul Guo 	IXGBE_WRITE_FLUSH(hw);
1273185c5677SPaul Guo 
127473cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
1275185c5677SPaul Guo 	IXGBE_WRITE_FLUSH(hw);
1276185c5677SPaul Guo 
1277185c5677SPaul Guo 	/* Poll init-done after we write FDIRCTRL register */
1278185c5677SPaul Guo 	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
1279185c5677SPaul Guo 		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
128069b5a878SDan McDonald 				   IXGBE_FDIRCTRL_INIT_DONE)
1281185c5677SPaul Guo 			break;
1282dc0cb1cdSDale Ghent 		msec_delay(1);
1283185c5677SPaul Guo 	}
1284185c5677SPaul Guo 	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
1285185c5677SPaul Guo 		DEBUGOUT("Flow Director Signature poll time exceeded!\n");
128663b3bba8SJerry Jelinek 		return IXGBE_ERR_FDIR_REINIT_FAILED;
1287185c5677SPaul Guo 	}
1288185c5677SPaul Guo 
1289185c5677SPaul Guo 	/* Clear FDIR statistics registers (read to clear) */
1290dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT);
1291dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT);
1292dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
1293dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
1294dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_FDIRLEN);
129573cd555cSBin Tu - Sun Microsystems - Beijing China 
129663b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
129773cd555cSBin Tu - Sun Microsystems - Beijing China }
129873cd555cSBin Tu - Sun Microsystems - Beijing China 
129963b3bba8SJerry Jelinek /**
130069b5a878SDan McDonald  *  ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
130163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
130269b5a878SDan McDonald  *  @fdirctrl: value to write to flow director control register
130363b3bba8SJerry Jelinek  **/
ixgbe_fdir_enable_82599(struct ixgbe_hw * hw,u32 fdirctrl)130469b5a878SDan McDonald static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
130573cd555cSBin Tu - Sun Microsystems - Beijing China {
130673cd555cSBin Tu - Sun Microsystems - Beijing China 	int i;
130773cd555cSBin Tu - Sun Microsystems - Beijing China 
130869b5a878SDan McDonald 	DEBUGFUNC("ixgbe_fdir_enable_82599");
130963b3bba8SJerry Jelinek 
131073cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Prime the keys for hashing */
131163b3bba8SJerry Jelinek 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
131263b3bba8SJerry Jelinek 	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
131373cd555cSBin Tu - Sun Microsystems - Beijing China 
131473cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
131573cd555cSBin Tu - Sun Microsystems - Beijing China 	 * Poll init-done after we write the register.  Estimated times:
131663b3bba8SJerry Jelinek 	 *      10G: PBALLOC = 11b, timing is 60us
131763b3bba8SJerry Jelinek 	 *       1G: PBALLOC = 11b, timing is 600us
131863b3bba8SJerry Jelinek 	 *     100M: PBALLOC = 11b, timing is 6ms
131973cd555cSBin Tu - Sun Microsystems - Beijing China 	 *
132063b3bba8SJerry Jelinek 	 *     Multiple these timings by 4 if under full Rx load
132173cd555cSBin Tu - Sun Microsystems - Beijing China 	 *
132273cd555cSBin Tu - Sun Microsystems - Beijing China 	 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
132373cd555cSBin Tu - Sun Microsystems - Beijing China 	 * 1 msec per poll time.  If we're at line rate and drop to 100M, then
132473cd555cSBin Tu - Sun Microsystems - Beijing China 	 * this might not finish in our poll time, but we can live with that
132573cd555cSBin Tu - Sun Microsystems - Beijing China 	 * for now.
132673cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
132773cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
132873cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
132973cd555cSBin Tu - Sun Microsystems - Beijing China 	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
133073cd555cSBin Tu - Sun Microsystems - Beijing China 		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
133169b5a878SDan McDonald 				   IXGBE_FDIRCTRL_INIT_DONE)
133273cd555cSBin Tu - Sun Microsystems - Beijing China 			break;
133373cd555cSBin Tu - Sun Microsystems - Beijing China 		msec_delay(1);
133473cd555cSBin Tu - Sun Microsystems - Beijing China 	}
133573cd555cSBin Tu - Sun Microsystems - Beijing China 
133669b5a878SDan McDonald 	if (i >= IXGBE_FDIR_INIT_DONE_POLL)
133769b5a878SDan McDonald 		DEBUGOUT("Flow Director poll time exceeded!\n");
133873cd555cSBin Tu - Sun Microsystems - Beijing China }
133973cd555cSBin Tu - Sun Microsystems - Beijing China 
134063b3bba8SJerry Jelinek /**
134169b5a878SDan McDonald  *  ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
134263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
134369b5a878SDan McDonald  *  @fdirctrl: value to write to flow director control register, initially
134469b5a878SDan McDonald  *	     contains just the value of the Rx packet buffer allocation
134563b3bba8SJerry Jelinek  **/
ixgbe_init_fdir_signature_82599(struct ixgbe_hw * hw,u32 fdirctrl)134669b5a878SDan McDonald s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
134773cd555cSBin Tu - Sun Microsystems - Beijing China {
134869b5a878SDan McDonald 	DEBUGFUNC("ixgbe_init_fdir_signature_82599");
134973cd555cSBin Tu - Sun Microsystems - Beijing China 
135073cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
135169b5a878SDan McDonald 	 * Continue setup of fdirctrl register bits:
135269b5a878SDan McDonald 	 *  Move the flexible bytes to use the ethertype - shift 6 words
135369b5a878SDan McDonald 	 *  Set the maximum length per hash bucket to 0xA filters
135469b5a878SDan McDonald 	 *  Send interrupt when 64 filters are left
135573cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
135669b5a878SDan McDonald 	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
135769b5a878SDan McDonald 		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
135869b5a878SDan McDonald 		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
135973cd555cSBin Tu - Sun Microsystems - Beijing China 
136069b5a878SDan McDonald 	/* write hashes and fdirctrl register, poll for completion */
136169b5a878SDan McDonald 	ixgbe_fdir_enable_82599(hw, fdirctrl);
136273cd555cSBin Tu - Sun Microsystems - Beijing China 
136363b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
136473cd555cSBin Tu - Sun Microsystems - Beijing China }
136573cd555cSBin Tu - Sun Microsystems - Beijing China 
136663b3bba8SJerry Jelinek /**
136769b5a878SDan McDonald  *  ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
136869b5a878SDan McDonald  *  @hw: pointer to hardware structure
136969b5a878SDan McDonald  *  @fdirctrl: value to write to flow director control register, initially
137069b5a878SDan McDonald  *	     contains just the value of the Rx packet buffer allocation
1371dc0cb1cdSDale Ghent  *  @cloud_mode: TRUE - cloud mode, FALSE - other mode
137263b3bba8SJerry Jelinek  **/
ixgbe_init_fdir_perfect_82599(struct ixgbe_hw * hw,u32 fdirctrl,bool cloud_mode)1373dc0cb1cdSDale Ghent s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
1374dc0cb1cdSDale Ghent 			bool cloud_mode)
137573cd555cSBin Tu - Sun Microsystems - Beijing China {
1376*48ed61a7SRobert Mustacchi 	UNREFERENCED_1PARAMETER(cloud_mode);
137769b5a878SDan McDonald 	DEBUGFUNC("ixgbe_init_fdir_perfect_82599");
137873cd555cSBin Tu - Sun Microsystems - Beijing China 
137973cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
138069b5a878SDan McDonald 	 * Continue setup of fdirctrl register bits:
138169b5a878SDan McDonald 	 *  Turn perfect match filtering on
138269b5a878SDan McDonald 	 *  Report hash in RSS field of Rx wb descriptor
1383dc0cb1cdSDale Ghent 	 *  Initialize the drop queue to queue 127
138469b5a878SDan McDonald 	 *  Move the flexible bytes to use the ethertype - shift 6 words
138569b5a878SDan McDonald 	 *  Set the maximum length per hash bucket to 0xA filters
138669b5a878SDan McDonald 	 *  Send interrupt when 64 (0x4 * 16) filters are left
138773cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
138869b5a878SDan McDonald 	fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH |
138969b5a878SDan McDonald 		    IXGBE_FDIRCTRL_REPORT_STATUS |
139069b5a878SDan McDonald 		    (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) |
139169b5a878SDan McDonald 		    (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
139269b5a878SDan McDonald 		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
139369b5a878SDan McDonald 		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
1394dc0cb1cdSDale Ghent 
1395dc0cb1cdSDale Ghent 	if (cloud_mode)
1396dc0cb1cdSDale Ghent 		fdirctrl |=(IXGBE_FDIRCTRL_FILTERMODE_CLOUD <<
1397dc0cb1cdSDale Ghent 					IXGBE_FDIRCTRL_FILTERMODE_SHIFT);
13983cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
139969b5a878SDan McDonald 	/* write hashes and fdirctrl register, poll for completion */
140069b5a878SDan McDonald 	ixgbe_fdir_enable_82599(hw, fdirctrl);
140173cd555cSBin Tu - Sun Microsystems - Beijing China 
140269b5a878SDan McDonald 	return IXGBE_SUCCESS;
140373cd555cSBin Tu - Sun Microsystems - Beijing China }
140473cd555cSBin Tu - Sun Microsystems - Beijing China 
1405dc0cb1cdSDale Ghent /**
1406dc0cb1cdSDale Ghent  *  ixgbe_set_fdir_drop_queue_82599 - Set Flow Director drop queue
1407dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
1408dc0cb1cdSDale Ghent  *  @dropqueue: Rx queue index used for the dropped packets
1409dc0cb1cdSDale Ghent  **/
ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw * hw,u8 dropqueue)1410dc0cb1cdSDale Ghent void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue)
1411dc0cb1cdSDale Ghent {
1412dc0cb1cdSDale Ghent 	u32 fdirctrl;
1413dc0cb1cdSDale Ghent 
1414dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_set_fdir_drop_queue_82599");
1415dc0cb1cdSDale Ghent 	/* Clear init done bit and drop queue field */
1416dc0cb1cdSDale Ghent 	fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
1417dc0cb1cdSDale Ghent 	fdirctrl &= ~(IXGBE_FDIRCTRL_DROP_Q_MASK | IXGBE_FDIRCTRL_INIT_DONE);
1418dc0cb1cdSDale Ghent 
1419dc0cb1cdSDale Ghent 	/* Set drop queue */
1420dc0cb1cdSDale Ghent 	fdirctrl |= (dropqueue << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
1421dc0cb1cdSDale Ghent 	if ((hw->mac.type == ixgbe_mac_X550) ||
1422*48ed61a7SRobert Mustacchi 	    (hw->mac.type == ixgbe_mac_X550EM_x) ||
1423*48ed61a7SRobert Mustacchi 	    (hw->mac.type == ixgbe_mac_X550EM_a))
1424dc0cb1cdSDale Ghent 		fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH;
1425dc0cb1cdSDale Ghent 
1426dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
1427dc0cb1cdSDale Ghent 			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
1428dc0cb1cdSDale Ghent 			 IXGBE_FDIRCMD_CLEARHT));
1429dc0cb1cdSDale Ghent 	IXGBE_WRITE_FLUSH(hw);
1430dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
1431dc0cb1cdSDale Ghent 			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
1432dc0cb1cdSDale Ghent 			 ~IXGBE_FDIRCMD_CLEARHT));
1433dc0cb1cdSDale Ghent 	IXGBE_WRITE_FLUSH(hw);
1434dc0cb1cdSDale Ghent 
1435dc0cb1cdSDale Ghent 	/* write hashes and fdirctrl register, poll for completion */
1436dc0cb1cdSDale Ghent 	ixgbe_fdir_enable_82599(hw, fdirctrl);
1437dc0cb1cdSDale Ghent }
1438dc0cb1cdSDale Ghent 
143973cd555cSBin Tu - Sun Microsystems - Beijing China /*
144063b3bba8SJerry Jelinek  * These defines allow us to quickly generate all of the necessary instructions
144163b3bba8SJerry Jelinek  * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
144263b3bba8SJerry Jelinek  * for values 0 through 15
144373cd555cSBin Tu - Sun Microsystems - Beijing China  */
144463b3bba8SJerry Jelinek #define IXGBE_ATR_COMMON_HASH_KEY \
144563b3bba8SJerry Jelinek 		(IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY)
144663b3bba8SJerry Jelinek #define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \
144769b5a878SDan McDonald do { \
144863b3bba8SJerry Jelinek 	u32 n = (_n); \
144963b3bba8SJerry Jelinek 	if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \
145063b3bba8SJerry Jelinek 		common_hash ^= lo_hash_dword >> n; \
145163b3bba8SJerry Jelinek 	else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
145263b3bba8SJerry Jelinek 		bucket_hash ^= lo_hash_dword >> n; \
145363b3bba8SJerry Jelinek 	else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \
145463b3bba8SJerry Jelinek 		sig_hash ^= lo_hash_dword << (16 - n); \
145563b3bba8SJerry Jelinek 	if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \
145663b3bba8SJerry Jelinek 		common_hash ^= hi_hash_dword >> n; \
145763b3bba8SJerry Jelinek 	else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
145863b3bba8SJerry Jelinek 		bucket_hash ^= hi_hash_dword >> n; \
145963b3bba8SJerry Jelinek 	else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \
146063b3bba8SJerry Jelinek 		sig_hash ^= hi_hash_dword << (16 - n); \
1461dc0cb1cdSDale Ghent } while (0)
146273cd555cSBin Tu - Sun Microsystems - Beijing China 
146363b3bba8SJerry Jelinek /**
146463b3bba8SJerry Jelinek  *  ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash
1465*48ed61a7SRobert Mustacchi  *  @input: input bitstream to compute the hash on
1466*48ed61a7SRobert Mustacchi  *  @common: compressed common input dword
146773cd555cSBin Tu - Sun Microsystems - Beijing China  *
146863b3bba8SJerry Jelinek  *  This function is almost identical to the function above but contains
1469dc0cb1cdSDale Ghent  *  several optimizations such as unwinding all of the loops, letting the
147063b3bba8SJerry Jelinek  *  compiler work out all of the conditional ifs since the keys are static
147163b3bba8SJerry Jelinek  *  defines, and computing two keys at once since the hashed dword stream
147263b3bba8SJerry Jelinek  *  will be the same for both keys.
147363b3bba8SJerry Jelinek  **/
ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,union ixgbe_atr_hash_dword common)147469b5a878SDan McDonald u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
147569b5a878SDan McDonald 				     union ixgbe_atr_hash_dword common)
147673cd555cSBin Tu - Sun Microsystems - Beijing China {
147763b3bba8SJerry Jelinek 	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
147863b3bba8SJerry Jelinek 	u32 sig_hash = 0, bucket_hash = 0, common_hash = 0;
14793cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
148063b3bba8SJerry Jelinek 	/* record the flow_vm_vlan bits as they are a key part to the hash */
148163b3bba8SJerry Jelinek 	flow_vm_vlan = IXGBE_NTOHL(input.dword);
148273cd555cSBin Tu - Sun Microsystems - Beijing China 
148363b3bba8SJerry Jelinek 	/* generate common hash dword */
148463b3bba8SJerry Jelinek 	hi_hash_dword = IXGBE_NTOHL(common.dword);
148573cd555cSBin Tu - Sun Microsystems - Beijing China 
148663b3bba8SJerry Jelinek 	/* low dword is word swapped version of common */
148763b3bba8SJerry Jelinek 	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
14883cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
148963b3bba8SJerry Jelinek 	/* apply flow ID/VM pool/VLAN ID bits to hash words */
149063b3bba8SJerry Jelinek 	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
149173cd555cSBin Tu - Sun Microsystems - Beijing China 
149263b3bba8SJerry Jelinek 	/* Process bits 0 and 16 */
149363b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(0);
149473cd555cSBin Tu - Sun Microsystems - Beijing China 
149563b3bba8SJerry Jelinek 	/*
149663b3bba8SJerry Jelinek 	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
149763b3bba8SJerry Jelinek 	 * delay this because bit 0 of the stream should not be processed
1498dc0cb1cdSDale Ghent 	 * so we do not add the VLAN until after bit 0 was processed
149963b3bba8SJerry Jelinek 	 */
150063b3bba8SJerry Jelinek 	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
150163b3bba8SJerry Jelinek 
150263b3bba8SJerry Jelinek 	/* Process remaining 30 bit of the key */
150363b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(1);
150463b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(2);
150563b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(3);
150663b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(4);
150763b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(5);
150863b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(6);
150963b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(7);
151063b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(8);
151163b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(9);
151263b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(10);
151363b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(11);
151463b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(12);
151563b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(13);
151663b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(14);
151763b3bba8SJerry Jelinek 	IXGBE_COMPUTE_SIG_HASH_ITERATION(15);
151863b3bba8SJerry Jelinek 
151963b3bba8SJerry Jelinek 	/* combine common_hash result with signature and bucket hashes */
152063b3bba8SJerry Jelinek 	bucket_hash ^= common_hash;
152163b3bba8SJerry Jelinek 	bucket_hash &= IXGBE_ATR_HASH_MASK;
15223cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
152363b3bba8SJerry Jelinek 	sig_hash ^= common_hash << 16;
152463b3bba8SJerry Jelinek 	sig_hash &= IXGBE_ATR_HASH_MASK << 16;
152573cd555cSBin Tu - Sun Microsystems - Beijing China 
152663b3bba8SJerry Jelinek 	/* return completed signature hash */
152763b3bba8SJerry Jelinek 	return sig_hash ^ bucket_hash;
152873cd555cSBin Tu - Sun Microsystems - Beijing China }
152973cd555cSBin Tu - Sun Microsystems - Beijing China 
153063b3bba8SJerry Jelinek /**
153163b3bba8SJerry Jelinek  *  ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter
153263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
153369b5a878SDan McDonald  *  @input: unique input dword
153469b5a878SDan McDonald  *  @common: compressed common input dword
153563b3bba8SJerry Jelinek  *  @queue: queue index to direct traffic to
1536dc0cb1cdSDale Ghent  *
1537dc0cb1cdSDale Ghent  * Note that the tunnel bit in input must not be set when the hardware
1538dc0cb1cdSDale Ghent  * tunneling support does not exist.
153963b3bba8SJerry Jelinek  **/
ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw * hw,union ixgbe_atr_hash_dword input,union ixgbe_atr_hash_dword common,u8 queue)1540dc0cb1cdSDale Ghent void ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
1541dc0cb1cdSDale Ghent 					   union ixgbe_atr_hash_dword input,
1542dc0cb1cdSDale Ghent 					   union ixgbe_atr_hash_dword common,
1543dc0cb1cdSDale Ghent 					   u8 queue)
154473cd555cSBin Tu - Sun Microsystems - Beijing China {
1545dc0cb1cdSDale Ghent 	u64 fdirhashcmd;
1546dc0cb1cdSDale Ghent 	u8 flow_type;
1547dc0cb1cdSDale Ghent 	bool tunnel;
1548dc0cb1cdSDale Ghent 	u32 fdircmd;
154973cd555cSBin Tu - Sun Microsystems - Beijing China 
15503cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
15513cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
155263b3bba8SJerry Jelinek 	/*
155363b3bba8SJerry Jelinek 	 * Get the flow_type in order to program FDIRCMD properly
155463b3bba8SJerry Jelinek 	 * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
1555dc0cb1cdSDale Ghent 	 * fifth is FDIRCMD.TUNNEL_FILTER
155663b3bba8SJerry Jelinek 	 */
1557dc0cb1cdSDale Ghent 	tunnel = !!(input.formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK);
1558dc0cb1cdSDale Ghent 	flow_type = input.formatted.flow_type &
1559dc0cb1cdSDale Ghent 		    (IXGBE_ATR_L4TYPE_TUNNEL_MASK - 1);
1560dc0cb1cdSDale Ghent 	switch (flow_type) {
156163b3bba8SJerry Jelinek 	case IXGBE_ATR_FLOW_TYPE_TCPV4:
156263b3bba8SJerry Jelinek 	case IXGBE_ATR_FLOW_TYPE_UDPV4:
156363b3bba8SJerry Jelinek 	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
156463b3bba8SJerry Jelinek 	case IXGBE_ATR_FLOW_TYPE_TCPV6:
156563b3bba8SJerry Jelinek 	case IXGBE_ATR_FLOW_TYPE_UDPV6:
156663b3bba8SJerry Jelinek 	case IXGBE_ATR_FLOW_TYPE_SCTPV6:
156763b3bba8SJerry Jelinek 		break;
156863b3bba8SJerry Jelinek 	default:
156963b3bba8SJerry Jelinek 		DEBUGOUT(" Error on flow type input\n");
1570dc0cb1cdSDale Ghent 		return;
157163b3bba8SJerry Jelinek 	}
157273cd555cSBin Tu - Sun Microsystems - Beijing China 
157363b3bba8SJerry Jelinek 	/* configure FDIRCMD register */
157463b3bba8SJerry Jelinek 	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
157569b5a878SDan McDonald 		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
1576dc0cb1cdSDale Ghent 	fdircmd |= (u32)flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
157763b3bba8SJerry Jelinek 	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
1578dc0cb1cdSDale Ghent 	if (tunnel)
1579dc0cb1cdSDale Ghent 		fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER;
158073cd555cSBin Tu - Sun Microsystems - Beijing China 
158173cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
158273cd555cSBin Tu - Sun Microsystems - Beijing China 	 * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
158373cd555cSBin Tu - Sun Microsystems - Beijing China 	 * is for FDIRCMD.  Then do a 64-bit register write from FDIRHASH.
158473cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
158563b3bba8SJerry Jelinek 	fdirhashcmd = (u64)fdircmd << 32;
158663b3bba8SJerry Jelinek 	fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
158763b3bba8SJerry Jelinek 	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
158873cd555cSBin Tu - Sun Microsystems - Beijing China 
158963b3bba8SJerry Jelinek 	DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
159073cd555cSBin Tu - Sun Microsystems - Beijing China 
1591dc0cb1cdSDale Ghent 	return;
159263b3bba8SJerry Jelinek }
159373cd555cSBin Tu - Sun Microsystems - Beijing China 
159469b5a878SDan McDonald #define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
159569b5a878SDan McDonald do { \
159669b5a878SDan McDonald 	u32 n = (_n); \
159769b5a878SDan McDonald 	if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
159869b5a878SDan McDonald 		bucket_hash ^= lo_hash_dword >> n; \
159969b5a878SDan McDonald 	if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
160069b5a878SDan McDonald 		bucket_hash ^= hi_hash_dword >> n; \
1601dc0cb1cdSDale Ghent } while (0)
1602dc0cb1cdSDale Ghent 
160369b5a878SDan McDonald /**
160469b5a878SDan McDonald  *  ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash
1605*48ed61a7SRobert Mustacchi  *  @input: input bitstream to compute the hash on
160669b5a878SDan McDonald  *  @input_mask: mask for the input bitstream
160769b5a878SDan McDonald  *
1608dc0cb1cdSDale Ghent  *  This function serves two main purposes.  First it applies the input_mask
160969b5a878SDan McDonald  *  to the atr_input resulting in a cleaned up atr_input data stream.
161069b5a878SDan McDonald  *  Secondly it computes the hash and stores it in the bkt_hash field at
161169b5a878SDan McDonald  *  the end of the input byte stream.  This way it will be available for
161269b5a878SDan McDonald  *  future use without needing to recompute the hash.
161369b5a878SDan McDonald  **/
ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input * input,union ixgbe_atr_input * input_mask)161469b5a878SDan McDonald void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
161569b5a878SDan McDonald 					  union ixgbe_atr_input *input_mask)
161669b5a878SDan McDonald {
161769b5a878SDan McDonald 
161869b5a878SDan McDonald 	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
161969b5a878SDan McDonald 	u32 bucket_hash = 0;
1620dc0cb1cdSDale Ghent 	u32 hi_dword = 0;
1621dc0cb1cdSDale Ghent 	u32 i = 0;
162269b5a878SDan McDonald 
162369b5a878SDan McDonald 	/* Apply masks to input data */
1624dc0cb1cdSDale Ghent 	for (i = 0; i < 14; i++)
1625dc0cb1cdSDale Ghent 		input->dword_stream[i]  &= input_mask->dword_stream[i];
162669b5a878SDan McDonald 
162769b5a878SDan McDonald 	/* record the flow_vm_vlan bits as they are a key part to the hash */
162869b5a878SDan McDonald 	flow_vm_vlan = IXGBE_NTOHL(input->dword_stream[0]);
162969b5a878SDan McDonald 
163069b5a878SDan McDonald 	/* generate common hash dword */
1631dc0cb1cdSDale Ghent 	for (i = 1; i <= 13; i++)
1632dc0cb1cdSDale Ghent 		hi_dword ^= input->dword_stream[i];
1633dc0cb1cdSDale Ghent 	hi_hash_dword = IXGBE_NTOHL(hi_dword);
163469b5a878SDan McDonald 
163569b5a878SDan McDonald 	/* low dword is word swapped version of common */
163669b5a878SDan McDonald 	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
163769b5a878SDan McDonald 
163869b5a878SDan McDonald 	/* apply flow ID/VM pool/VLAN ID bits to hash words */
163969b5a878SDan McDonald 	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
164069b5a878SDan McDonald 
164169b5a878SDan McDonald 	/* Process bits 0 and 16 */
164269b5a878SDan McDonald 	IXGBE_COMPUTE_BKT_HASH_ITERATION(0);
164369b5a878SDan McDonald 
164469b5a878SDan McDonald 	/*
164569b5a878SDan McDonald 	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
164669b5a878SDan McDonald 	 * delay this because bit 0 of the stream should not be processed
1647dc0cb1cdSDale Ghent 	 * so we do not add the VLAN until after bit 0 was processed
164869b5a878SDan McDonald 	 */
164969b5a878SDan McDonald 	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
165069b5a878SDan McDonald 
165169b5a878SDan McDonald 	/* Process remaining 30 bit of the key */
1652dc0cb1cdSDale Ghent 	for (i = 1; i <= 15; i++)
1653dc0cb1cdSDale Ghent 		IXGBE_COMPUTE_BKT_HASH_ITERATION(i);
165469b5a878SDan McDonald 
165569b5a878SDan McDonald 	/*
165669b5a878SDan McDonald 	 * Limit hash to 13 bits since max bucket count is 8K.
165769b5a878SDan McDonald 	 * Store result at the end of the input stream.
165869b5a878SDan McDonald 	 */
165969b5a878SDan McDonald 	input->formatted.bkt_hash = bucket_hash & 0x1FFF;
166069b5a878SDan McDonald }
166169b5a878SDan McDonald 
166263b3bba8SJerry Jelinek /**
1663dc0cb1cdSDale Ghent  *  ixgbe_get_fdirtcpm_82599 - generate a TCP port from atr_input_masks
166463b3bba8SJerry Jelinek  *  @input_mask: mask to be bit swapped
166563b3bba8SJerry Jelinek  *
166663b3bba8SJerry Jelinek  *  The source and destination port masks for flow director are bit swapped
166763b3bba8SJerry Jelinek  *  in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc.  In order to
166863b3bba8SJerry Jelinek  *  generate a correctly swapped value we need to bit swap the mask and that
166963b3bba8SJerry Jelinek  *  is what is accomplished by this function.
167063b3bba8SJerry Jelinek  **/
ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input * input_mask)167169b5a878SDan McDonald static u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask)
167263b3bba8SJerry Jelinek {
167369b5a878SDan McDonald 	u32 mask = IXGBE_NTOHS(input_mask->formatted.dst_port);
167463b3bba8SJerry Jelinek 	mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
167569b5a878SDan McDonald 	mask |= IXGBE_NTOHS(input_mask->formatted.src_port);
167663b3bba8SJerry Jelinek 	mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
167763b3bba8SJerry Jelinek 	mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
167863b3bba8SJerry Jelinek 	mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
167963b3bba8SJerry Jelinek 	return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8);
168063b3bba8SJerry Jelinek }
168173cd555cSBin Tu - Sun Microsystems - Beijing China 
168263b3bba8SJerry Jelinek /*
168363b3bba8SJerry Jelinek  * These two macros are meant to address the fact that we have registers
168463b3bba8SJerry Jelinek  * that are either all or in part big-endian.  As a result on big-endian
168563b3bba8SJerry Jelinek  * systems we will end up byte swapping the value to little-endian before
168663b3bba8SJerry Jelinek  * it is byte swapped again and written to the hardware in the original
168763b3bba8SJerry Jelinek  * big-endian format.
168863b3bba8SJerry Jelinek  */
168963b3bba8SJerry Jelinek #define IXGBE_STORE_AS_BE32(_value) \
169063b3bba8SJerry Jelinek 	(((u32)(_value) >> 24) | (((u32)(_value) & 0x00FF0000) >> 8) | \
169163b3bba8SJerry Jelinek 	 (((u32)(_value) & 0x0000FF00) << 8) | ((u32)(_value) << 24))
169273cd555cSBin Tu - Sun Microsystems - Beijing China 
169363b3bba8SJerry Jelinek #define IXGBE_WRITE_REG_BE32(a, reg, value) \
169463b3bba8SJerry Jelinek 	IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(IXGBE_NTOHL(value)))
169573cd555cSBin Tu - Sun Microsystems - Beijing China 
169663b3bba8SJerry Jelinek #define IXGBE_STORE_AS_BE16(_value) \
169769b5a878SDan McDonald 	IXGBE_NTOHS(((u16)(_value) >> 8) | ((u16)(_value) << 8))
169873cd555cSBin Tu - Sun Microsystems - Beijing China 
ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw * hw,union ixgbe_atr_input * input_mask,bool cloud_mode)169969b5a878SDan McDonald s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
1700dc0cb1cdSDale Ghent 				    union ixgbe_atr_input *input_mask, bool cloud_mode)
170173cd555cSBin Tu - Sun Microsystems - Beijing China {
170269b5a878SDan McDonald 	/* mask IPv6 since it is currently not supported */
170369b5a878SDan McDonald 	u32 fdirm = IXGBE_FDIRM_DIPv6;
170469b5a878SDan McDonald 	u32 fdirtcpm;
1705dc0cb1cdSDale Ghent 	u32 fdirip6m;
1706*48ed61a7SRobert Mustacchi 	UNREFERENCED_1PARAMETER(cloud_mode);
170769b5a878SDan McDonald 	DEBUGFUNC("ixgbe_fdir_set_atr_input_mask_82599");
170873cd555cSBin Tu - Sun Microsystems - Beijing China 
17095b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/*
17105b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
17115b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * are zero, then assume a full mask for that field.  Also assume that
17125b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * a VLAN of 0 is unspecified, so mask that out as well.  L4type
17135b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * cannot be masked out in this implementation.
17145b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 *
17155b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
17165b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * point in time.
17175b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 */
17185b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
171969b5a878SDan McDonald 	/* verify bucket hash is cleared on hash generation */
172069b5a878SDan McDonald 	if (input_mask->formatted.bkt_hash)
172169b5a878SDan McDonald 		DEBUGOUT(" bucket hash should always be 0 in mask\n");
172269b5a878SDan McDonald 
172369b5a878SDan McDonald 	/* Program FDIRM and verify partial masks */
172469b5a878SDan McDonald 	switch (input_mask->formatted.vm_pool & 0x7F) {
172569b5a878SDan McDonald 	case 0x0:
172669b5a878SDan McDonald 		fdirm |= IXGBE_FDIRM_POOL;
172769b5a878SDan McDonald 	case 0x7F:
17285b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		break;
172969b5a878SDan McDonald 	default:
173069b5a878SDan McDonald 		DEBUGOUT(" Error on vm pool mask\n");
173169b5a878SDan McDonald 		return IXGBE_ERR_CONFIG;
173269b5a878SDan McDonald 	}
173369b5a878SDan McDonald 
173469b5a878SDan McDonald 	switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) {
173569b5a878SDan McDonald 	case 0x0:
173669b5a878SDan McDonald 		fdirm |= IXGBE_FDIRM_L4P;
173769b5a878SDan McDonald 		if (input_mask->formatted.dst_port ||
173869b5a878SDan McDonald 		    input_mask->formatted.src_port) {
173969b5a878SDan McDonald 			DEBUGOUT(" Error on src/dst port mask\n");
174069b5a878SDan McDonald 			return IXGBE_ERR_CONFIG;
174169b5a878SDan McDonald 		}
174269b5a878SDan McDonald 	case IXGBE_ATR_L4TYPE_MASK:
17435b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		break;
174469b5a878SDan McDonald 	default:
174569b5a878SDan McDonald 		DEBUGOUT(" Error on flow type mask\n");
174669b5a878SDan McDonald 		return IXGBE_ERR_CONFIG;
174769b5a878SDan McDonald 	}
174869b5a878SDan McDonald 
174969b5a878SDan McDonald 	switch (IXGBE_NTOHS(input_mask->formatted.vlan_id) & 0xEFFF) {
175063b3bba8SJerry Jelinek 	case 0x0000:
1751*48ed61a7SRobert Mustacchi 		/* mask VLAN ID */
175269b5a878SDan McDonald 		fdirm |= IXGBE_FDIRM_VLANID;
1753e5c421abSToomas Soome 		/* FALLTHROUGH */
175469b5a878SDan McDonald 	case 0x0FFF:
175569b5a878SDan McDonald 		/* mask VLAN priority */
175669b5a878SDan McDonald 		fdirm |= IXGBE_FDIRM_VLANP;
175769b5a878SDan McDonald 		break;
175869b5a878SDan McDonald 	case 0xE000:
1759*48ed61a7SRobert Mustacchi 		/* mask VLAN ID only */
176069b5a878SDan McDonald 		fdirm |= IXGBE_FDIRM_VLANID;
1761*48ed61a7SRobert Mustacchi 		/* fall through */
176269b5a878SDan McDonald 	case 0xEFFF:
176369b5a878SDan McDonald 		/* no VLAN fields masked */
17645b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		break;
176563b3bba8SJerry Jelinek 	default:
176663b3bba8SJerry Jelinek 		DEBUGOUT(" Error on VLAN mask\n");
176763b3bba8SJerry Jelinek 		return IXGBE_ERR_CONFIG;
17685b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	}
17695b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
177069b5a878SDan McDonald 	switch (input_mask->formatted.flex_bytes & 0xFFFF) {
177169b5a878SDan McDonald 	case 0x0000:
1772*48ed61a7SRobert Mustacchi 		/* Mask Flex Bytes */
177369b5a878SDan McDonald 		fdirm |= IXGBE_FDIRM_FLEX;
1774*48ed61a7SRobert Mustacchi 		/* fall through */
177569b5a878SDan McDonald 	case 0xFFFF:
177669b5a878SDan McDonald 		break;
177769b5a878SDan McDonald 	default:
177869b5a878SDan McDonald 		DEBUGOUT(" Error on flexible byte mask\n");
177969b5a878SDan McDonald 		return IXGBE_ERR_CONFIG;
178063b3bba8SJerry Jelinek 	}
17815b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
1782dc0cb1cdSDale Ghent 	if (cloud_mode) {
1783dc0cb1cdSDale Ghent 		fdirm |= IXGBE_FDIRM_L3P;
1784dc0cb1cdSDale Ghent 		fdirip6m = ((u32) 0xFFFFU << IXGBE_FDIRIP6M_DIPM_SHIFT);
1785dc0cb1cdSDale Ghent 		fdirip6m |= IXGBE_FDIRIP6M_ALWAYS_MASK;
17865b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
1787dc0cb1cdSDale Ghent 		switch (input_mask->formatted.inner_mac[0] & 0xFF) {
1788dc0cb1cdSDale Ghent 		case 0x00:
1789dc0cb1cdSDale Ghent 			/* Mask inner MAC, fall through */
1790dc0cb1cdSDale Ghent 			fdirip6m |= IXGBE_FDIRIP6M_INNER_MAC;
1791dc0cb1cdSDale Ghent 		case 0xFF:
1792dc0cb1cdSDale Ghent 			break;
1793dc0cb1cdSDale Ghent 		default:
1794dc0cb1cdSDale Ghent 			DEBUGOUT(" Error on inner_mac byte mask\n");
1795dc0cb1cdSDale Ghent 			return IXGBE_ERR_CONFIG;
1796dc0cb1cdSDale Ghent 		}
179763b3bba8SJerry Jelinek 
1798dc0cb1cdSDale Ghent 		switch (input_mask->formatted.tni_vni & 0xFFFFFFFF) {
1799dc0cb1cdSDale Ghent 		case 0x0:
1800dc0cb1cdSDale Ghent 			/* Mask vxlan id */
1801dc0cb1cdSDale Ghent 			fdirip6m |= IXGBE_FDIRIP6M_TNI_VNI;
1802dc0cb1cdSDale Ghent 			break;
1803dc0cb1cdSDale Ghent 		case 0x00FFFFFF:
1804dc0cb1cdSDale Ghent 			fdirip6m |= IXGBE_FDIRIP6M_TNI_VNI_24;
1805dc0cb1cdSDale Ghent 			break;
1806dc0cb1cdSDale Ghent 		case 0xFFFFFFFF:
1807dc0cb1cdSDale Ghent 			break;
1808dc0cb1cdSDale Ghent 		default:
1809dc0cb1cdSDale Ghent 			DEBUGOUT(" Error on TNI/VNI byte mask\n");
1810dc0cb1cdSDale Ghent 			return IXGBE_ERR_CONFIG;
1811dc0cb1cdSDale Ghent 		}
181263b3bba8SJerry Jelinek 
1813dc0cb1cdSDale Ghent 		switch (input_mask->formatted.tunnel_type & 0xFFFF) {
1814dc0cb1cdSDale Ghent 		case 0x0:
1815dc0cb1cdSDale Ghent 			/* Mask turnnel type, fall through */
1816dc0cb1cdSDale Ghent 			fdirip6m |= IXGBE_FDIRIP6M_TUNNEL_TYPE;
1817dc0cb1cdSDale Ghent 		case 0xFFFF:
1818dc0cb1cdSDale Ghent 			break;
1819dc0cb1cdSDale Ghent 		default:
1820dc0cb1cdSDale Ghent 			DEBUGOUT(" Error on tunnel type byte mask\n");
1821dc0cb1cdSDale Ghent 			return IXGBE_ERR_CONFIG;
1822dc0cb1cdSDale Ghent 		}
1823dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIP6M, fdirip6m);
1824dc0cb1cdSDale Ghent 
1825*48ed61a7SRobert Mustacchi 		/* Set all bits in FDIRTCPM, FDIRUDPM, FDIRSCTPM,
1826*48ed61a7SRobert Mustacchi 		 * FDIRSIP4M and FDIRDIP4M in cloud mode to allow
1827*48ed61a7SRobert Mustacchi 		 * L3/L3 packets to tunnel.
1828dc0cb1cdSDale Ghent 		 */
1829dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xFFFFFFFF);
1830dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xFFFFFFFF);
1831dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M, 0xFFFFFFFF);
1832dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, 0xFFFFFFFF);
1833*48ed61a7SRobert Mustacchi 		switch (hw->mac.type) {
1834*48ed61a7SRobert Mustacchi 		case ixgbe_mac_X550:
1835*48ed61a7SRobert Mustacchi 		case ixgbe_mac_X550EM_x:
1836*48ed61a7SRobert Mustacchi 		case ixgbe_mac_X550EM_a:
1837*48ed61a7SRobert Mustacchi 			IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, 0xFFFFFFFF);
1838*48ed61a7SRobert Mustacchi 			break;
1839*48ed61a7SRobert Mustacchi 		default:
1840*48ed61a7SRobert Mustacchi 			break;
1841*48ed61a7SRobert Mustacchi 		}
1842dc0cb1cdSDale Ghent 	}
1843dc0cb1cdSDale Ghent 
1844dc0cb1cdSDale Ghent 	/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
1845dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
1846dc0cb1cdSDale Ghent 
1847dc0cb1cdSDale Ghent 	if (!cloud_mode) {
1848dc0cb1cdSDale Ghent 		/* store the TCP/UDP port masks, bit reversed from port
1849dc0cb1cdSDale Ghent 		 * layout */
1850dc0cb1cdSDale Ghent 		fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
1851dc0cb1cdSDale Ghent 
1852dc0cb1cdSDale Ghent 		/* write both the same so that UDP and TCP use the same mask */
1853dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
1854dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
1855dc0cb1cdSDale Ghent 		/* also use it for SCTP */
1856dc0cb1cdSDale Ghent 		switch (hw->mac.type) {
1857dc0cb1cdSDale Ghent 		case ixgbe_mac_X550:
1858dc0cb1cdSDale Ghent 		case ixgbe_mac_X550EM_x:
1859*48ed61a7SRobert Mustacchi 		case ixgbe_mac_X550EM_a:
1860dc0cb1cdSDale Ghent 			IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm);
1861dc0cb1cdSDale Ghent 			break;
1862dc0cb1cdSDale Ghent 		default:
1863dc0cb1cdSDale Ghent 			break;
1864dc0cb1cdSDale Ghent 		}
186563b3bba8SJerry Jelinek 
1866dc0cb1cdSDale Ghent 		/* store source and destination IP masks (big-enian) */
1867dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
1868dc0cb1cdSDale Ghent 				     ~input_mask->formatted.src_ip[0]);
1869dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
1870dc0cb1cdSDale Ghent 				     ~input_mask->formatted.dst_ip[0]);
1871dc0cb1cdSDale Ghent 	}
187269b5a878SDan McDonald 	return IXGBE_SUCCESS;
187369b5a878SDan McDonald }
187463b3bba8SJerry Jelinek 
ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw * hw,union ixgbe_atr_input * input,u16 soft_id,u8 queue,bool cloud_mode)187569b5a878SDan McDonald s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
187669b5a878SDan McDonald 					  union ixgbe_atr_input *input,
1877dc0cb1cdSDale Ghent 					  u16 soft_id, u8 queue, bool cloud_mode)
187869b5a878SDan McDonald {
187969b5a878SDan McDonald 	u32 fdirport, fdirvlan, fdirhash, fdircmd;
1880dc0cb1cdSDale Ghent 	u32 addr_low, addr_high;
1881dc0cb1cdSDale Ghent 	u32 cloud_type = 0;
1882dc0cb1cdSDale Ghent 	s32 err;
1883*48ed61a7SRobert Mustacchi 	UNREFERENCED_1PARAMETER(cloud_mode);
188469b5a878SDan McDonald 
188569b5a878SDan McDonald 	DEBUGFUNC("ixgbe_fdir_write_perfect_filter_82599");
1886dc0cb1cdSDale Ghent 	if (!cloud_mode) {
1887dc0cb1cdSDale Ghent 		/* currently IPv6 is not supported, must be programmed with 0 */
1888dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
1889dc0cb1cdSDale Ghent 				     input->formatted.src_ip[0]);
1890dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
1891dc0cb1cdSDale Ghent 				     input->formatted.src_ip[1]);
1892dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
1893dc0cb1cdSDale Ghent 				     input->formatted.src_ip[2]);
1894dc0cb1cdSDale Ghent 
1895dc0cb1cdSDale Ghent 		/* record the source address (big-endian) */
1896dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA,
1897dc0cb1cdSDale Ghent 			input->formatted.src_ip[0]);
1898dc0cb1cdSDale Ghent 
1899dc0cb1cdSDale Ghent 		/* record the first 32 bits of the destination address
1900dc0cb1cdSDale Ghent 		 * (big-endian) */
1901dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA,
1902dc0cb1cdSDale Ghent 			input->formatted.dst_ip[0]);
1903dc0cb1cdSDale Ghent 
1904dc0cb1cdSDale Ghent 		/* record source and destination port (little-endian)*/
1905dc0cb1cdSDale Ghent 		fdirport = IXGBE_NTOHS(input->formatted.dst_port);
1906dc0cb1cdSDale Ghent 		fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
1907dc0cb1cdSDale Ghent 		fdirport |= IXGBE_NTOHS(input->formatted.src_port);
1908dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
1909dc0cb1cdSDale Ghent 	}
191069b5a878SDan McDonald 
1911dc0cb1cdSDale Ghent 	/* record VLAN (little-endian) and flex_bytes(big-endian) */
191269b5a878SDan McDonald 	fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes);
191369b5a878SDan McDonald 	fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
191469b5a878SDan McDonald 	fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id);
191569b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
191663b3bba8SJerry Jelinek 
1917dc0cb1cdSDale Ghent 	if (cloud_mode) {
1918dc0cb1cdSDale Ghent 		if (input->formatted.tunnel_type != 0)
1919dc0cb1cdSDale Ghent 			cloud_type = 0x80000000;
1920dc0cb1cdSDale Ghent 
1921dc0cb1cdSDale Ghent 		addr_low = ((u32)input->formatted.inner_mac[0] |
1922dc0cb1cdSDale Ghent 				((u32)input->formatted.inner_mac[1] << 8) |
1923dc0cb1cdSDale Ghent 				((u32)input->formatted.inner_mac[2] << 16) |
1924dc0cb1cdSDale Ghent 				((u32)input->formatted.inner_mac[3] << 24));
1925dc0cb1cdSDale Ghent 		addr_high = ((u32)input->formatted.inner_mac[4] |
1926dc0cb1cdSDale Ghent 				((u32)input->formatted.inner_mac[5] << 8));
1927dc0cb1cdSDale Ghent 		cloud_type |= addr_high;
1928dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0), addr_low);
1929dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1), cloud_type);
1930dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2), input->formatted.tni_vni);
1931dc0cb1cdSDale Ghent 	}
1932dc0cb1cdSDale Ghent 
193369b5a878SDan McDonald 	/* configure FDIRHASH register */
193469b5a878SDan McDonald 	fdirhash = input->formatted.bkt_hash;
193569b5a878SDan McDonald 	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
193669b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
193769b5a878SDan McDonald 
193869b5a878SDan McDonald 	/*
193969b5a878SDan McDonald 	 * flush all previous writes to make certain registers are
194069b5a878SDan McDonald 	 * programmed prior to issuing the command
194169b5a878SDan McDonald 	 */
194269b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
194363b3bba8SJerry Jelinek 
194463b3bba8SJerry Jelinek 	/* configure FDIRCMD register */
194563b3bba8SJerry Jelinek 	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
194663b3bba8SJerry Jelinek 		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
194769b5a878SDan McDonald 	if (queue == IXGBE_FDIR_DROP_QUEUE)
194869b5a878SDan McDonald 		fdircmd |= IXGBE_FDIRCMD_DROP;
1949dc0cb1cdSDale Ghent 	if (input->formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK)
1950dc0cb1cdSDale Ghent 		fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER;
195163b3bba8SJerry Jelinek 	fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
195263b3bba8SJerry Jelinek 	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
195369b5a878SDan McDonald 	fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
195463b3bba8SJerry Jelinek 
195573cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
1956dc0cb1cdSDale Ghent 	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
1957dc0cb1cdSDale Ghent 	if (err) {
1958dc0cb1cdSDale Ghent 		DEBUGOUT("Flow Director command did not complete!\n");
1959dc0cb1cdSDale Ghent 		return err;
1960dc0cb1cdSDale Ghent 	}
196173cd555cSBin Tu - Sun Microsystems - Beijing China 
196263b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
196373cd555cSBin Tu - Sun Microsystems - Beijing China }
196473cd555cSBin Tu - Sun Microsystems - Beijing China 
ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw * hw,union ixgbe_atr_input * input,u16 soft_id)196569b5a878SDan McDonald s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
196669b5a878SDan McDonald 					  union ixgbe_atr_input *input,
196769b5a878SDan McDonald 					  u16 soft_id)
196869b5a878SDan McDonald {
196969b5a878SDan McDonald 	u32 fdirhash;
1970dc0cb1cdSDale Ghent 	u32 fdircmd;
1971dc0cb1cdSDale Ghent 	s32 err;
197269b5a878SDan McDonald 
197369b5a878SDan McDonald 	/* configure FDIRHASH register */
197469b5a878SDan McDonald 	fdirhash = input->formatted.bkt_hash;
197569b5a878SDan McDonald 	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
197669b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
197769b5a878SDan McDonald 
197869b5a878SDan McDonald 	/* flush hash to HW */
197969b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
198069b5a878SDan McDonald 
198169b5a878SDan McDonald 	/* Query if filter is present */
198269b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
198369b5a878SDan McDonald 
1984dc0cb1cdSDale Ghent 	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
1985dc0cb1cdSDale Ghent 	if (err) {
1986dc0cb1cdSDale Ghent 		DEBUGOUT("Flow Director command did not complete!\n");
1987dc0cb1cdSDale Ghent 		return err;
198869b5a878SDan McDonald 	}
198969b5a878SDan McDonald 
199069b5a878SDan McDonald 	/* if filter exists in hardware then remove it */
199169b5a878SDan McDonald 	if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
199269b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
199369b5a878SDan McDonald 		IXGBE_WRITE_FLUSH(hw);
199469b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
199569b5a878SDan McDonald 				IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
199669b5a878SDan McDonald 	}
199769b5a878SDan McDonald 
1998dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
199969b5a878SDan McDonald }
200069b5a878SDan McDonald 
200169b5a878SDan McDonald /**
200269b5a878SDan McDonald  *  ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
200369b5a878SDan McDonald  *  @hw: pointer to hardware structure
200469b5a878SDan McDonald  *  @input: input bitstream
200569b5a878SDan McDonald  *  @input_mask: mask for the input bitstream
200669b5a878SDan McDonald  *  @soft_id: software index for the filters
200769b5a878SDan McDonald  *  @queue: queue index to direct traffic to
2008*48ed61a7SRobert Mustacchi  *  @cloud_mode: unused
200969b5a878SDan McDonald  *
201069b5a878SDan McDonald  *  Note that the caller to this function must lock before calling, since the
201169b5a878SDan McDonald  *  hardware writes must be protected from one another.
201269b5a878SDan McDonald  **/
ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw * hw,union ixgbe_atr_input * input,union ixgbe_atr_input * input_mask,u16 soft_id,u8 queue,bool cloud_mode)201369b5a878SDan McDonald s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
201469b5a878SDan McDonald 					union ixgbe_atr_input *input,
201569b5a878SDan McDonald 					union ixgbe_atr_input *input_mask,
2016dc0cb1cdSDale Ghent 					u16 soft_id, u8 queue, bool cloud_mode)
201769b5a878SDan McDonald {
201869b5a878SDan McDonald 	s32 err = IXGBE_ERR_CONFIG;
2019*48ed61a7SRobert Mustacchi 	UNREFERENCED_1PARAMETER(cloud_mode);
202069b5a878SDan McDonald 
202169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599");
202269b5a878SDan McDonald 
202369b5a878SDan McDonald 	/*
202469b5a878SDan McDonald 	 * Check flow_type formatting, and bail out before we touch the hardware
202569b5a878SDan McDonald 	 * if there's a configuration issue
202669b5a878SDan McDonald 	 */
202769b5a878SDan McDonald 	switch (input->formatted.flow_type) {
202869b5a878SDan McDonald 	case IXGBE_ATR_FLOW_TYPE_IPV4:
2029dc0cb1cdSDale Ghent 	case IXGBE_ATR_FLOW_TYPE_TUNNELED_IPV4:
203069b5a878SDan McDonald 		input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK;
203169b5a878SDan McDonald 		if (input->formatted.dst_port || input->formatted.src_port) {
203269b5a878SDan McDonald 			DEBUGOUT(" Error on src/dst port\n");
203369b5a878SDan McDonald 			return IXGBE_ERR_CONFIG;
203469b5a878SDan McDonald 		}
203569b5a878SDan McDonald 		break;
203669b5a878SDan McDonald 	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
2037dc0cb1cdSDale Ghent 	case IXGBE_ATR_FLOW_TYPE_TUNNELED_SCTPV4:
203869b5a878SDan McDonald 		if (input->formatted.dst_port || input->formatted.src_port) {
203969b5a878SDan McDonald 			DEBUGOUT(" Error on src/dst port\n");
204069b5a878SDan McDonald 			return IXGBE_ERR_CONFIG;
204169b5a878SDan McDonald 		}
2042e5c421abSToomas Soome 		/* FALLTHROUGH */
204369b5a878SDan McDonald 	case IXGBE_ATR_FLOW_TYPE_TCPV4:
2044dc0cb1cdSDale Ghent 	case IXGBE_ATR_FLOW_TYPE_TUNNELED_TCPV4:
204569b5a878SDan McDonald 	case IXGBE_ATR_FLOW_TYPE_UDPV4:
2046dc0cb1cdSDale Ghent 	case IXGBE_ATR_FLOW_TYPE_TUNNELED_UDPV4:
204769b5a878SDan McDonald 		input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
204869b5a878SDan McDonald 						  IXGBE_ATR_L4TYPE_MASK;
204969b5a878SDan McDonald 		break;
205069b5a878SDan McDonald 	default:
205169b5a878SDan McDonald 		DEBUGOUT(" Error on flow type input\n");
205269b5a878SDan McDonald 		return err;
205369b5a878SDan McDonald 	}
205469b5a878SDan McDonald 
205569b5a878SDan McDonald 	/* program input mask into the HW */
2056dc0cb1cdSDale Ghent 	err = ixgbe_fdir_set_input_mask_82599(hw, input_mask, cloud_mode);
205769b5a878SDan McDonald 	if (err)
205869b5a878SDan McDonald 		return err;
205969b5a878SDan McDonald 
206069b5a878SDan McDonald 	/* apply mask and compute/store hash */
206169b5a878SDan McDonald 	ixgbe_atr_compute_perfect_hash_82599(input, input_mask);
206269b5a878SDan McDonald 
206369b5a878SDan McDonald 	/* program filters to filter memory */
206469b5a878SDan McDonald 	return ixgbe_fdir_write_perfect_filter_82599(hw, input,
2065dc0cb1cdSDale Ghent 						     soft_id, queue, cloud_mode);
206669b5a878SDan McDonald }
206769b5a878SDan McDonald 
206863b3bba8SJerry Jelinek /**
206963b3bba8SJerry Jelinek  *  ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
207063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
207163b3bba8SJerry Jelinek  *  @reg: analog register to read
207263b3bba8SJerry Jelinek  *  @val: read value
207373cd555cSBin Tu - Sun Microsystems - Beijing China  *
207463b3bba8SJerry Jelinek  *  Performs read operation to Omer analog register specified.
207563b3bba8SJerry Jelinek  **/
ixgbe_read_analog_reg8_82599(struct ixgbe_hw * hw,u32 reg,u8 * val)207663b3bba8SJerry Jelinek s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val)
207773cd555cSBin Tu - Sun Microsystems - Beijing China {
207873cd555cSBin Tu - Sun Microsystems - Beijing China 	u32  core_ctl;
207973cd555cSBin Tu - Sun Microsystems - Beijing China 
20803cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_read_analog_reg8_82599");
20813cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
208273cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD |
208369b5a878SDan McDonald 			(reg << 8));
208473cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
208573cd555cSBin Tu - Sun Microsystems - Beijing China 	usec_delay(10);
208673cd555cSBin Tu - Sun Microsystems - Beijing China 	core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL);
208773cd555cSBin Tu - Sun Microsystems - Beijing China 	*val = (u8)core_ctl;
208873cd555cSBin Tu - Sun Microsystems - Beijing China 
208963b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
209073cd555cSBin Tu - Sun Microsystems - Beijing China }
209173cd555cSBin Tu - Sun Microsystems - Beijing China 
209263b3bba8SJerry Jelinek /**
209363b3bba8SJerry Jelinek  *  ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register
209463b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
209563b3bba8SJerry Jelinek  *  @reg: atlas register to write
209663b3bba8SJerry Jelinek  *  @val: value to write
209773cd555cSBin Tu - Sun Microsystems - Beijing China  *
209863b3bba8SJerry Jelinek  *  Performs write operation to Omer analog register specified.
209963b3bba8SJerry Jelinek  **/
ixgbe_write_analog_reg8_82599(struct ixgbe_hw * hw,u32 reg,u8 val)210063b3bba8SJerry Jelinek s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val)
210173cd555cSBin Tu - Sun Microsystems - Beijing China {
210273cd555cSBin Tu - Sun Microsystems - Beijing China 	u32  core_ctl;
210373cd555cSBin Tu - Sun Microsystems - Beijing China 
21043cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_write_analog_reg8_82599");
21053cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
210673cd555cSBin Tu - Sun Microsystems - Beijing China 	core_ctl = (reg << 8) | val;
210773cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl);
210873cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
210973cd555cSBin Tu - Sun Microsystems - Beijing China 	usec_delay(10);
211073cd555cSBin Tu - Sun Microsystems - Beijing China 
211163b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
211273cd555cSBin Tu - Sun Microsystems - Beijing China }
211373cd555cSBin Tu - Sun Microsystems - Beijing China 
211463b3bba8SJerry Jelinek /**
211569b5a878SDan McDonald  *  ixgbe_start_hw_82599 - Prepare hardware for Tx/Rx
211663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
211773cd555cSBin Tu - Sun Microsystems - Beijing China  *
211863b3bba8SJerry Jelinek  *  Starts the hardware using the generic start_hw function
211963b3bba8SJerry Jelinek  *  and the generation start_hw function.
212063b3bba8SJerry Jelinek  *  Then performs revision-specific operations, if any.
212163b3bba8SJerry Jelinek  **/
ixgbe_start_hw_82599(struct ixgbe_hw * hw)212269b5a878SDan McDonald s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw)
212373cd555cSBin Tu - Sun Microsystems - Beijing China {
212473cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 ret_val = IXGBE_SUCCESS;
212573cd555cSBin Tu - Sun Microsystems - Beijing China 
212669b5a878SDan McDonald 	DEBUGFUNC("ixgbe_start_hw_82599");
21273cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
212873cd555cSBin Tu - Sun Microsystems - Beijing China 	ret_val = ixgbe_start_hw_generic(hw);
212963b3bba8SJerry Jelinek 	if (ret_val != IXGBE_SUCCESS)
213063b3bba8SJerry Jelinek 		goto out;
213173cd555cSBin Tu - Sun Microsystems - Beijing China 
213263b3bba8SJerry Jelinek 	ret_val = ixgbe_start_hw_gen2(hw);
213363b3bba8SJerry Jelinek 	if (ret_val != IXGBE_SUCCESS)
213463b3bba8SJerry Jelinek 		goto out;
213519843f01SPaul Guo 
2136185c5677SPaul Guo 	/* We need to run link autotry after the driver loads */
213763b3bba8SJerry Jelinek 	hw->mac.autotry_restart = TRUE;
2138185c5677SPaul Guo 
2139185c5677SPaul Guo 	if (ret_val == IXGBE_SUCCESS)
2140185c5677SPaul Guo 		ret_val = ixgbe_verify_fw_version_82599(hw);
214163b3bba8SJerry Jelinek out:
214263b3bba8SJerry Jelinek 	return ret_val;
214373cd555cSBin Tu - Sun Microsystems - Beijing China }
214473cd555cSBin Tu - Sun Microsystems - Beijing China 
214563b3bba8SJerry Jelinek /**
214663b3bba8SJerry Jelinek  *  ixgbe_identify_phy_82599 - Get physical layer module
214763b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
214873cd555cSBin Tu - Sun Microsystems - Beijing China  *
214963b3bba8SJerry Jelinek  *  Determines the physical layer module found on the current adapter.
215063b3bba8SJerry Jelinek  *  If PHY already detected, maintains current PHY type in hw struct,
215163b3bba8SJerry Jelinek  *  otherwise executes the PHY detection routine.
215263b3bba8SJerry Jelinek  **/
ixgbe_identify_phy_82599(struct ixgbe_hw * hw)215363b3bba8SJerry Jelinek s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
215473cd555cSBin Tu - Sun Microsystems - Beijing China {
2155dc0cb1cdSDale Ghent 	s32 status;
215673cd555cSBin Tu - Sun Microsystems - Beijing China 
21573cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_identify_phy_82599");
21583cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
215973cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Detect PHY if not unknown - returns success if already detected. */
216073cd555cSBin Tu - Sun Microsystems - Beijing China 	status = ixgbe_identify_phy_generic(hw);
216163b3bba8SJerry Jelinek 	if (status != IXGBE_SUCCESS) {
216263b3bba8SJerry Jelinek 		/* 82599 10GBASE-T requires an external PHY */
216363b3bba8SJerry Jelinek 		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
2164dc0cb1cdSDale Ghent 			return status;
216563b3bba8SJerry Jelinek 		else
216669b5a878SDan McDonald 			status = ixgbe_identify_module_generic(hw);
216763b3bba8SJerry Jelinek 	}
216863b3bba8SJerry Jelinek 
216973cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Set PHY type none if no PHY detected */
217073cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->phy.type == ixgbe_phy_unknown) {
217173cd555cSBin Tu - Sun Microsystems - Beijing China 		hw->phy.type = ixgbe_phy_none;
2172dc0cb1cdSDale Ghent 		return IXGBE_SUCCESS;
217373cd555cSBin Tu - Sun Microsystems - Beijing China 	}
217473cd555cSBin Tu - Sun Microsystems - Beijing China 
217573cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Return error if SFP module has been detected but is not supported */
217673cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
2177dc0cb1cdSDale Ghent 		return IXGBE_ERR_SFP_NOT_SUPPORTED;
217873cd555cSBin Tu - Sun Microsystems - Beijing China 
217963b3bba8SJerry Jelinek 	return status;
218073cd555cSBin Tu - Sun Microsystems - Beijing China }
218173cd555cSBin Tu - Sun Microsystems - Beijing China 
218263b3bba8SJerry Jelinek /**
218363b3bba8SJerry Jelinek  *  ixgbe_get_supported_physical_layer_82599 - Returns physical layer type
218463b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
218573cd555cSBin Tu - Sun Microsystems - Beijing China  *
218663b3bba8SJerry Jelinek  *  Determines physical layer capabilities of the current configuration.
218763b3bba8SJerry Jelinek  **/
ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw * hw)2188*48ed61a7SRobert Mustacchi u64 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
218973cd555cSBin Tu - Sun Microsystems - Beijing China {
2190*48ed61a7SRobert Mustacchi 	u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
219173cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
219273cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
219373cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
219473cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
219573cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
219673cd555cSBin Tu - Sun Microsystems - Beijing China 	u16 ext_ability = 0;
219773cd555cSBin Tu - Sun Microsystems - Beijing China 
21983cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_support_physical_layer_82599");
21993cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
220073cd555cSBin Tu - Sun Microsystems - Beijing China 	hw->phy.ops.identify(hw);
220173cd555cSBin Tu - Sun Microsystems - Beijing China 
220263b3bba8SJerry Jelinek 	switch (hw->phy.type) {
220363b3bba8SJerry Jelinek 	case ixgbe_phy_tn:
220463b3bba8SJerry Jelinek 	case ixgbe_phy_cu_unknown:
220573cd555cSBin Tu - Sun Microsystems - Beijing China 		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
220663b3bba8SJerry Jelinek 		IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
220773cd555cSBin Tu - Sun Microsystems - Beijing China 		if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
220873cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
220973cd555cSBin Tu - Sun Microsystems - Beijing China 		if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
221073cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
221173cd555cSBin Tu - Sun Microsystems - Beijing China 		if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
221273cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
221373cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
221463b3bba8SJerry Jelinek 	default:
221563b3bba8SJerry Jelinek 		break;
221673cd555cSBin Tu - Sun Microsystems - Beijing China 	}
221773cd555cSBin Tu - Sun Microsystems - Beijing China 
221873cd555cSBin Tu - Sun Microsystems - Beijing China 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
221973cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_1G_AN:
222073cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
222173cd555cSBin Tu - Sun Microsystems - Beijing China 		if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) {
222273cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
222373cd555cSBin Tu - Sun Microsystems - Beijing China 			    IXGBE_PHYSICAL_LAYER_1000BASE_BX;
222473cd555cSBin Tu - Sun Microsystems - Beijing China 			goto out;
2225dc0cb1cdSDale Ghent 		} else
2226dc0cb1cdSDale Ghent 			/* SFI mode so read SFP module */
2227dc0cb1cdSDale Ghent 			goto sfp_check;
2228dc0cb1cdSDale Ghent 		break;
222973cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
223073cd555cSBin Tu - Sun Microsystems - Beijing China 		if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4)
223173cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
223273cd555cSBin Tu - Sun Microsystems - Beijing China 		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4)
223373cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
2234185c5677SPaul Guo 		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI)
2235185c5677SPaul Guo 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI;
223673cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
2237dc0cb1cdSDale Ghent 		break;
223873cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_10G_SERIAL:
223973cd555cSBin Tu - Sun Microsystems - Beijing China 		if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) {
224073cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR;
224173cd555cSBin Tu - Sun Microsystems - Beijing China 			goto out;
224273cd555cSBin Tu - Sun Microsystems - Beijing China 		} else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)
224373cd555cSBin Tu - Sun Microsystems - Beijing China 			goto sfp_check;
224473cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
224573cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
224673cd555cSBin Tu - Sun Microsystems - Beijing China 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
224773cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KX_SUPP)
224873cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
224973cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
225073cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
225173cd555cSBin Tu - Sun Microsystems - Beijing China 		if (autoc & IXGBE_AUTOC_KR_SUPP)
225273cd555cSBin Tu - Sun Microsystems - Beijing China 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
225373cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
2254dc0cb1cdSDale Ghent 		break;
225573cd555cSBin Tu - Sun Microsystems - Beijing China 	default:
225673cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
2257dc0cb1cdSDale Ghent 		break;
225873cd555cSBin Tu - Sun Microsystems - Beijing China 	}
225973cd555cSBin Tu - Sun Microsystems - Beijing China 
226073cd555cSBin Tu - Sun Microsystems - Beijing China sfp_check:
226163b3bba8SJerry Jelinek 	/* SFP check must be done last since DA modules are sometimes used to
226273cd555cSBin Tu - Sun Microsystems - Beijing China 	 * test KR mode -  we need to id KR mode correctly before SFP module.
226363b3bba8SJerry Jelinek 	 * Call identify_sfp because the pluggable module may have changed */
2264dc0cb1cdSDale Ghent 	physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw);
226573cd555cSBin Tu - Sun Microsystems - Beijing China out:
226663b3bba8SJerry Jelinek 	return physical_layer;
226773cd555cSBin Tu - Sun Microsystems - Beijing China }
226873cd555cSBin Tu - Sun Microsystems - Beijing China 
226963b3bba8SJerry Jelinek /**
227063b3bba8SJerry Jelinek  *  ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599
227163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
227263b3bba8SJerry Jelinek  *  @regval: register value to write to RXCTRL
227373cd555cSBin Tu - Sun Microsystems - Beijing China  *
227463b3bba8SJerry Jelinek  *  Enables the Rx DMA unit for 82599
227563b3bba8SJerry Jelinek  **/
ixgbe_enable_rx_dma_82599(struct ixgbe_hw * hw,u32 regval)227663b3bba8SJerry Jelinek s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
227773cd555cSBin Tu - Sun Microsystems - Beijing China {
227873cd555cSBin Tu - Sun Microsystems - Beijing China 
22793cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_enable_rx_dma_82599");
22803cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
228173cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
228273cd555cSBin Tu - Sun Microsystems - Beijing China 	 * Workaround for 82599 silicon errata when enabling the Rx datapath.
228373cd555cSBin Tu - Sun Microsystems - Beijing China 	 * If traffic is incoming before we enable the Rx unit, it could hang
228473cd555cSBin Tu - Sun Microsystems - Beijing China 	 * the Rx DMA unit.  Therefore, make sure the security engine is
228573cd555cSBin Tu - Sun Microsystems - Beijing China 	 * completely disabled prior to enabling the Rx unit.
228673cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
228773cd555cSBin Tu - Sun Microsystems - Beijing China 
228869b5a878SDan McDonald 	hw->mac.ops.disable_sec_rx_path(hw);
228973cd555cSBin Tu - Sun Microsystems - Beijing China 
2290dc0cb1cdSDale Ghent 	if (regval & IXGBE_RXCTRL_RXEN)
2291dc0cb1cdSDale Ghent 		ixgbe_enable_rx(hw);
2292dc0cb1cdSDale Ghent 	else
2293dc0cb1cdSDale Ghent 		ixgbe_disable_rx(hw);
229469b5a878SDan McDonald 
229569b5a878SDan McDonald 	hw->mac.ops.enable_sec_rx_path(hw);
229673cd555cSBin Tu - Sun Microsystems - Beijing China 
229763b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
229873cd555cSBin Tu - Sun Microsystems - Beijing China }
229973cd555cSBin Tu - Sun Microsystems - Beijing China 
230063b3bba8SJerry Jelinek /**
2301dc0cb1cdSDale Ghent  *  ixgbe_verify_fw_version_82599 - verify FW version for 82599
230263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
2303185c5677SPaul Guo  *
230463b3bba8SJerry Jelinek  *  Verifies that installed the firmware version is 0.6 or higher
230563b3bba8SJerry Jelinek  *  for SFI devices. All 82599 SFI devices should have version 0.6 or higher.
2306185c5677SPaul Guo  *
230763b3bba8SJerry Jelinek  *  Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or
230863b3bba8SJerry Jelinek  *  if the FW version is not supported.
230963b3bba8SJerry Jelinek  **/
ixgbe_verify_fw_version_82599(struct ixgbe_hw * hw)231063b3bba8SJerry Jelinek static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
2311185c5677SPaul Guo {
2312185c5677SPaul Guo 	s32 status = IXGBE_ERR_EEPROM_VERSION;
2313185c5677SPaul Guo 	u16 fw_offset, fw_ptp_cfg_offset;
2314dc0cb1cdSDale Ghent 	u16 fw_version;
2315185c5677SPaul Guo 
23163cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_verify_fw_version_82599");
23173cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
2318185c5677SPaul Guo 	/* firmware check is only necessary for SFI devices */
2319185c5677SPaul Guo 	if (hw->phy.media_type != ixgbe_media_type_fiber) {
2320185c5677SPaul Guo 		status = IXGBE_SUCCESS;
2321185c5677SPaul Guo 		goto fw_version_out;
2322185c5677SPaul Guo 	}
2323185c5677SPaul Guo 
2324185c5677SPaul Guo 	/* get the offset to the Firmware Module block */
2325dc0cb1cdSDale Ghent 	if (hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset)) {
2326dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
2327dc0cb1cdSDale Ghent 			      "eeprom read at offset %d failed", IXGBE_FW_PTR);
2328dc0cb1cdSDale Ghent 		return IXGBE_ERR_EEPROM_VERSION;
2329dc0cb1cdSDale Ghent 	}
2330185c5677SPaul Guo 
2331185c5677SPaul Guo 	if ((fw_offset == 0) || (fw_offset == 0xFFFF))
2332185c5677SPaul Guo 		goto fw_version_out;
2333185c5677SPaul Guo 
2334185c5677SPaul Guo 	/* get the offset to the Pass Through Patch Configuration block */
2335dc0cb1cdSDale Ghent 	if (hw->eeprom.ops.read(hw, (fw_offset +
233669b5a878SDan McDonald 				 IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR),
2337dc0cb1cdSDale Ghent 				 &fw_ptp_cfg_offset)) {
2338dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
2339dc0cb1cdSDale Ghent 			      "eeprom read at offset %d failed",
2340dc0cb1cdSDale Ghent 			      fw_offset +
2341dc0cb1cdSDale Ghent 			      IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR);
2342dc0cb1cdSDale Ghent 		return IXGBE_ERR_EEPROM_VERSION;
2343dc0cb1cdSDale Ghent 	}
2344185c5677SPaul Guo 
2345185c5677SPaul Guo 	if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
2346185c5677SPaul Guo 		goto fw_version_out;
2347185c5677SPaul Guo 
2348185c5677SPaul Guo 	/* get the firmware version */
2349dc0cb1cdSDale Ghent 	if (hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset +
2350dc0cb1cdSDale Ghent 			    IXGBE_FW_PATCH_VERSION_4), &fw_version)) {
2351dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
2352dc0cb1cdSDale Ghent 			      "eeprom read at offset %d failed",
2353dc0cb1cdSDale Ghent 			      fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4);
2354dc0cb1cdSDale Ghent 		return IXGBE_ERR_EEPROM_VERSION;
2355dc0cb1cdSDale Ghent 	}
2356185c5677SPaul Guo 
2357185c5677SPaul Guo 	if (fw_version > 0x5)
2358185c5677SPaul Guo 		status = IXGBE_SUCCESS;
2359185c5677SPaul Guo 
2360185c5677SPaul Guo fw_version_out:
236163b3bba8SJerry Jelinek 	return status;
2362185c5677SPaul Guo }
236319843f01SPaul Guo 
236463b3bba8SJerry Jelinek /**
236563b3bba8SJerry Jelinek  *  ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state.
236663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
236763b3bba8SJerry Jelinek  *
236863b3bba8SJerry Jelinek  *  Returns TRUE if the LESM FW module is present and enabled. Otherwise
236963b3bba8SJerry Jelinek  *  returns FALSE. Smart Speed must be disabled if LESM FW module is enabled.
237063b3bba8SJerry Jelinek  **/
ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw * hw)237163b3bba8SJerry Jelinek bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
237219843f01SPaul Guo {
237363b3bba8SJerry Jelinek 	bool lesm_enabled = FALSE;
237463b3bba8SJerry Jelinek 	u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
237563b3bba8SJerry Jelinek 	s32 status;
237619843f01SPaul Guo 
237763b3bba8SJerry Jelinek 	DEBUGFUNC("ixgbe_verify_lesm_fw_enabled_82599");
237819843f01SPaul Guo 
237963b3bba8SJerry Jelinek 	/* get the offset to the Firmware Module block */
238063b3bba8SJerry Jelinek 	status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
238119843f01SPaul Guo 
238263b3bba8SJerry Jelinek 	if ((status != IXGBE_SUCCESS) ||
238363b3bba8SJerry Jelinek 	    (fw_offset == 0) || (fw_offset == 0xFFFF))
238463b3bba8SJerry Jelinek 		goto out;
238563b3bba8SJerry Jelinek 
238663b3bba8SJerry Jelinek 	/* get the offset to the LESM Parameters block */
238763b3bba8SJerry Jelinek 	status = hw->eeprom.ops.read(hw, (fw_offset +
238869b5a878SDan McDonald 				     IXGBE_FW_LESM_PARAMETERS_PTR),
238969b5a878SDan McDonald 				     &fw_lesm_param_offset);
239063b3bba8SJerry Jelinek 
239163b3bba8SJerry Jelinek 	if ((status != IXGBE_SUCCESS) ||
239263b3bba8SJerry Jelinek 	    (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF))
239363b3bba8SJerry Jelinek 		goto out;
239463b3bba8SJerry Jelinek 
2395dc0cb1cdSDale Ghent 	/* get the LESM state word */
239663b3bba8SJerry Jelinek 	status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset +
239769b5a878SDan McDonald 				     IXGBE_FW_LESM_STATE_1),
239869b5a878SDan McDonald 				     &fw_lesm_state);
239963b3bba8SJerry Jelinek 
240063b3bba8SJerry Jelinek 	if ((status == IXGBE_SUCCESS) &&
240163b3bba8SJerry Jelinek 	    (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
240263b3bba8SJerry Jelinek 		lesm_enabled = TRUE;
240363b3bba8SJerry Jelinek 
240463b3bba8SJerry Jelinek out:
240563b3bba8SJerry Jelinek 	return lesm_enabled;
240619843f01SPaul Guo }
240763b3bba8SJerry Jelinek 
240869b5a878SDan McDonald /**
240969b5a878SDan McDonald  *  ixgbe_read_eeprom_buffer_82599 - Read EEPROM word(s) using
241069b5a878SDan McDonald  *  fastest available method
241169b5a878SDan McDonald  *
241269b5a878SDan McDonald  *  @hw: pointer to hardware structure
241369b5a878SDan McDonald  *  @offset: offset of  word in EEPROM to read
241469b5a878SDan McDonald  *  @words: number of words
241569b5a878SDan McDonald  *  @data: word(s) read from the EEPROM
241669b5a878SDan McDonald  *
241769b5a878SDan McDonald  *  Retrieves 16 bit word(s) read from EEPROM
241869b5a878SDan McDonald  **/
ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)241969b5a878SDan McDonald static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
242069b5a878SDan McDonald 					  u16 words, u16 *data)
242169b5a878SDan McDonald {
242269b5a878SDan McDonald 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
242369b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_CONFIG;
242469b5a878SDan McDonald 
242569b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_eeprom_buffer_82599");
242669b5a878SDan McDonald 
242769b5a878SDan McDonald 	/*
242869b5a878SDan McDonald 	 * If EEPROM is detected and can be addressed using 14 bits,
242969b5a878SDan McDonald 	 * use EERD otherwise use bit bang
243069b5a878SDan McDonald 	 */
243169b5a878SDan McDonald 	if ((eeprom->type == ixgbe_eeprom_spi) &&
243269b5a878SDan McDonald 	    (offset + (words - 1) <= IXGBE_EERD_MAX_ADDR))
243369b5a878SDan McDonald 		ret_val = ixgbe_read_eerd_buffer_generic(hw, offset, words,
243469b5a878SDan McDonald 							 data);
243569b5a878SDan McDonald 	else
243669b5a878SDan McDonald 		ret_val = ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset,
243769b5a878SDan McDonald 								    words,
243869b5a878SDan McDonald 								    data);
243969b5a878SDan McDonald 
244069b5a878SDan McDonald 	return ret_val;
244169b5a878SDan McDonald }
244269b5a878SDan McDonald 
244369b5a878SDan McDonald /**
244469b5a878SDan McDonald  *  ixgbe_read_eeprom_82599 - Read EEPROM word using
244569b5a878SDan McDonald  *  fastest available method
244669b5a878SDan McDonald  *
244769b5a878SDan McDonald  *  @hw: pointer to hardware structure
244869b5a878SDan McDonald  *  @offset: offset of  word in the EEPROM to read
244969b5a878SDan McDonald  *  @data: word read from the EEPROM
245069b5a878SDan McDonald  *
245169b5a878SDan McDonald  *  Reads a 16 bit word from the EEPROM
245269b5a878SDan McDonald  **/
ixgbe_read_eeprom_82599(struct ixgbe_hw * hw,u16 offset,u16 * data)245369b5a878SDan McDonald static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
245469b5a878SDan McDonald 				   u16 offset, u16 *data)
245569b5a878SDan McDonald {
245669b5a878SDan McDonald 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
245769b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_CONFIG;
245869b5a878SDan McDonald 
245969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_eeprom_82599");
246069b5a878SDan McDonald 
246169b5a878SDan McDonald 	/*
246269b5a878SDan McDonald 	 * If EEPROM is detected and can be addressed using 14 bits,
246369b5a878SDan McDonald 	 * use EERD otherwise use bit bang
246469b5a878SDan McDonald 	 */
246569b5a878SDan McDonald 	if ((eeprom->type == ixgbe_eeprom_spi) &&
246669b5a878SDan McDonald 	    (offset <= IXGBE_EERD_MAX_ADDR))
246769b5a878SDan McDonald 		ret_val = ixgbe_read_eerd_generic(hw, offset, data);
246869b5a878SDan McDonald 	else
246969b5a878SDan McDonald 		ret_val = ixgbe_read_eeprom_bit_bang_generic(hw, offset, data);
247069b5a878SDan McDonald 
247169b5a878SDan McDonald 	return ret_val;
247269b5a878SDan McDonald }
247369b5a878SDan McDonald 
2474dc0cb1cdSDale Ghent /**
2475dc0cb1cdSDale Ghent  * ixgbe_reset_pipeline_82599 - perform pipeline reset
2476dc0cb1cdSDale Ghent  *
2477dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
2478dc0cb1cdSDale Ghent  *
2479dc0cb1cdSDale Ghent  * Reset pipeline by asserting Restart_AN together with LMS change to ensure
2480dc0cb1cdSDale Ghent  * full pipeline reset.  This function assumes the SW/FW lock is held.
2481dc0cb1cdSDale Ghent  **/
ixgbe_reset_pipeline_82599(struct ixgbe_hw * hw)2482dc0cb1cdSDale Ghent s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
2483dc0cb1cdSDale Ghent {
2484dc0cb1cdSDale Ghent 	s32 ret_val;
2485dc0cb1cdSDale Ghent 	u32 anlp1_reg = 0;
2486dc0cb1cdSDale Ghent 	u32 i, autoc_reg, autoc2_reg;
2487dc0cb1cdSDale Ghent 
2488dc0cb1cdSDale Ghent 	/* Enable link if disabled in NVM */
2489dc0cb1cdSDale Ghent 	autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
2490dc0cb1cdSDale Ghent 	if (autoc2_reg & IXGBE_AUTOC2_LINK_DISABLE_MASK) {
2491dc0cb1cdSDale Ghent 		autoc2_reg &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK;
2492dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
2493dc0cb1cdSDale Ghent 		IXGBE_WRITE_FLUSH(hw);
2494dc0cb1cdSDale Ghent 	}
2495dc0cb1cdSDale Ghent 
2496dc0cb1cdSDale Ghent 	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
2497dc0cb1cdSDale Ghent 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
2498dc0cb1cdSDale Ghent 	/* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
2499dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
2500dc0cb1cdSDale Ghent 			autoc_reg ^ (0x4 << IXGBE_AUTOC_LMS_SHIFT));
2501dc0cb1cdSDale Ghent 	/* Wait for AN to leave state 0 */
2502dc0cb1cdSDale Ghent 	for (i = 0; i < 10; i++) {
2503dc0cb1cdSDale Ghent 		msec_delay(4);
2504dc0cb1cdSDale Ghent 		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
2505dc0cb1cdSDale Ghent 		if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)
2506dc0cb1cdSDale Ghent 			break;
2507dc0cb1cdSDale Ghent 	}
2508dc0cb1cdSDale Ghent 
2509dc0cb1cdSDale Ghent 	if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
2510dc0cb1cdSDale Ghent 		DEBUGOUT("auto negotiation not completed\n");
2511dc0cb1cdSDale Ghent 		ret_val = IXGBE_ERR_RESET_FAILED;
2512dc0cb1cdSDale Ghent 		goto reset_pipeline_out;
2513dc0cb1cdSDale Ghent 	}
251463b3bba8SJerry Jelinek 
2515dc0cb1cdSDale Ghent 	ret_val = IXGBE_SUCCESS;
2516dc0cb1cdSDale Ghent 
2517dc0cb1cdSDale Ghent reset_pipeline_out:
2518dc0cb1cdSDale Ghent 	/* Write AUTOC register with original LMS field and Restart_AN */
2519dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
2520dc0cb1cdSDale Ghent 	IXGBE_WRITE_FLUSH(hw);
2521dc0cb1cdSDale Ghent 
2522dc0cb1cdSDale Ghent 	return ret_val;
2523dc0cb1cdSDale Ghent }
2524dc0cb1cdSDale Ghent 
2525dc0cb1cdSDale Ghent /**
2526dc0cb1cdSDale Ghent  *  ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C
2527dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
2528dc0cb1cdSDale Ghent  *  @byte_offset: byte offset to read
2529*48ed61a7SRobert Mustacchi  *  @dev_addr: address to read from
2530dc0cb1cdSDale Ghent  *  @data: value read
2531dc0cb1cdSDale Ghent  *
2532dc0cb1cdSDale Ghent  *  Performs byte read operation to SFP module's EEPROM over I2C interface at
2533dc0cb1cdSDale Ghent  *  a specified device address.
2534dc0cb1cdSDale Ghent  **/
ixgbe_read_i2c_byte_82599(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 * data)2535dc0cb1cdSDale Ghent static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
2536dc0cb1cdSDale Ghent 				u8 dev_addr, u8 *data)
2537dc0cb1cdSDale Ghent {
2538dc0cb1cdSDale Ghent 	u32 esdp;
2539dc0cb1cdSDale Ghent 	s32 status;
2540dc0cb1cdSDale Ghent 	s32 timeout = 200;
2541dc0cb1cdSDale Ghent 
2542dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_read_i2c_byte_82599");
2543dc0cb1cdSDale Ghent 
2544dc0cb1cdSDale Ghent 	if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
2545dc0cb1cdSDale Ghent 		/* Acquire I2C bus ownership. */
2546dc0cb1cdSDale Ghent 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2547dc0cb1cdSDale Ghent 		esdp |= IXGBE_ESDP_SDP0;
2548dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
2549dc0cb1cdSDale Ghent 		IXGBE_WRITE_FLUSH(hw);
2550dc0cb1cdSDale Ghent 
2551dc0cb1cdSDale Ghent 		while (timeout) {
2552dc0cb1cdSDale Ghent 			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2553dc0cb1cdSDale Ghent 			if (esdp & IXGBE_ESDP_SDP1)
2554dc0cb1cdSDale Ghent 				break;
2555dc0cb1cdSDale Ghent 
2556dc0cb1cdSDale Ghent 			msec_delay(5);
2557dc0cb1cdSDale Ghent 			timeout--;
2558dc0cb1cdSDale Ghent 		}
2559dc0cb1cdSDale Ghent 
2560dc0cb1cdSDale Ghent 		if (!timeout) {
2561dc0cb1cdSDale Ghent 			DEBUGOUT("Driver can't access resource,"
2562dc0cb1cdSDale Ghent 				 " acquiring I2C bus timeout.\n");
2563dc0cb1cdSDale Ghent 			status = IXGBE_ERR_I2C;
2564dc0cb1cdSDale Ghent 			goto release_i2c_access;
2565dc0cb1cdSDale Ghent 		}
2566dc0cb1cdSDale Ghent 	}
2567dc0cb1cdSDale Ghent 
2568dc0cb1cdSDale Ghent 	status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data);
2569dc0cb1cdSDale Ghent 
2570dc0cb1cdSDale Ghent release_i2c_access:
2571dc0cb1cdSDale Ghent 
2572dc0cb1cdSDale Ghent 	if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
2573dc0cb1cdSDale Ghent 		/* Release I2C bus ownership. */
2574dc0cb1cdSDale Ghent 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2575dc0cb1cdSDale Ghent 		esdp &= ~IXGBE_ESDP_SDP0;
2576dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
2577dc0cb1cdSDale Ghent 		IXGBE_WRITE_FLUSH(hw);
2578dc0cb1cdSDale Ghent 	}
2579dc0cb1cdSDale Ghent 
2580dc0cb1cdSDale Ghent 	return status;
2581dc0cb1cdSDale Ghent }
2582dc0cb1cdSDale Ghent 
2583dc0cb1cdSDale Ghent /**
2584dc0cb1cdSDale Ghent  *  ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C
2585dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
2586dc0cb1cdSDale Ghent  *  @byte_offset: byte offset to write
2587*48ed61a7SRobert Mustacchi  *  @dev_addr: address to read from
2588dc0cb1cdSDale Ghent  *  @data: value to write
2589dc0cb1cdSDale Ghent  *
2590dc0cb1cdSDale Ghent  *  Performs byte write operation to SFP module's EEPROM over I2C interface at
2591dc0cb1cdSDale Ghent  *  a specified device address.
2592dc0cb1cdSDale Ghent  **/
ixgbe_write_i2c_byte_82599(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 data)2593dc0cb1cdSDale Ghent static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
2594dc0cb1cdSDale Ghent 				 u8 dev_addr, u8 data)
2595dc0cb1cdSDale Ghent {
2596dc0cb1cdSDale Ghent 	u32 esdp;
2597dc0cb1cdSDale Ghent 	s32 status;
2598dc0cb1cdSDale Ghent 	s32 timeout = 200;
2599dc0cb1cdSDale Ghent 
2600dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_write_i2c_byte_82599");
2601dc0cb1cdSDale Ghent 
2602dc0cb1cdSDale Ghent 	if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
2603dc0cb1cdSDale Ghent 		/* Acquire I2C bus ownership. */
2604dc0cb1cdSDale Ghent 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2605dc0cb1cdSDale Ghent 		esdp |= IXGBE_ESDP_SDP0;
2606dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
2607dc0cb1cdSDale Ghent 		IXGBE_WRITE_FLUSH(hw);
2608dc0cb1cdSDale Ghent 
2609dc0cb1cdSDale Ghent 		while (timeout) {
2610dc0cb1cdSDale Ghent 			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2611dc0cb1cdSDale Ghent 			if (esdp & IXGBE_ESDP_SDP1)
2612dc0cb1cdSDale Ghent 				break;
2613dc0cb1cdSDale Ghent 
2614dc0cb1cdSDale Ghent 			msec_delay(5);
2615dc0cb1cdSDale Ghent 			timeout--;
2616dc0cb1cdSDale Ghent 		}
2617dc0cb1cdSDale Ghent 
2618dc0cb1cdSDale Ghent 		if (!timeout) {
2619dc0cb1cdSDale Ghent 			DEBUGOUT("Driver can't access resource,"
2620dc0cb1cdSDale Ghent 				 " acquiring I2C bus timeout.\n");
2621dc0cb1cdSDale Ghent 			status = IXGBE_ERR_I2C;
2622dc0cb1cdSDale Ghent 			goto release_i2c_access;
2623dc0cb1cdSDale Ghent 		}
2624dc0cb1cdSDale Ghent 	}
2625dc0cb1cdSDale Ghent 
2626dc0cb1cdSDale Ghent 	status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data);
2627dc0cb1cdSDale Ghent 
2628dc0cb1cdSDale Ghent release_i2c_access:
2629dc0cb1cdSDale Ghent 
2630dc0cb1cdSDale Ghent 	if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
2631dc0cb1cdSDale Ghent 		/* Release I2C bus ownership. */
2632dc0cb1cdSDale Ghent 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2633dc0cb1cdSDale Ghent 		esdp &= ~IXGBE_ESDP_SDP0;
2634dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
2635dc0cb1cdSDale Ghent 		IXGBE_WRITE_FLUSH(hw);
2636dc0cb1cdSDale Ghent 	}
2637dc0cb1cdSDale Ghent 
2638dc0cb1cdSDale Ghent 	return status;
2639dc0cb1cdSDale Ghent }
2640