xref: /freebsd/sys/dev/ixgbe/ixgbe_82599.c (revision 89d4096950c4db748e39758c941cfb708c2ff808)
1770e416bSJack F Vogel /******************************************************************************
27282444bSPedro F. Giffuni   SPDX-License-Identifier: BSD-3-Clause
3770e416bSJack F Vogel 
48455e365SKevin Bowling   Copyright (c) 2001-2020, Intel Corporation
5770e416bSJack F Vogel   All rights reserved.
6770e416bSJack F Vogel 
7770e416bSJack F Vogel   Redistribution and use in source and binary forms, with or without
8770e416bSJack F Vogel   modification, are permitted provided that the following conditions are met:
9770e416bSJack F Vogel 
10770e416bSJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
11770e416bSJack F Vogel       this list of conditions and the following disclaimer.
12770e416bSJack F Vogel 
13770e416bSJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
14770e416bSJack F Vogel       notice, this list of conditions and the following disclaimer in the
15770e416bSJack F Vogel       documentation and/or other materials provided with the distribution.
16770e416bSJack F Vogel 
17770e416bSJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
18770e416bSJack F Vogel       contributors may be used to endorse or promote products derived from
19770e416bSJack F Vogel       this software without specific prior written permission.
20770e416bSJack F Vogel 
21770e416bSJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22770e416bSJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23770e416bSJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24770e416bSJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25770e416bSJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26770e416bSJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27770e416bSJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28770e416bSJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29770e416bSJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30770e416bSJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31770e416bSJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
32770e416bSJack F Vogel 
33770e416bSJack F Vogel ******************************************************************************/
34770e416bSJack F Vogel 
35770e416bSJack F Vogel #include "ixgbe_type.h"
3685d0a26eSJack F Vogel #include "ixgbe_82599.h"
37770e416bSJack F Vogel #include "ixgbe_api.h"
38770e416bSJack F Vogel #include "ixgbe_common.h"
39770e416bSJack F Vogel #include "ixgbe_phy.h"
40770e416bSJack F Vogel 
41758cc3dcSJack F Vogel #define IXGBE_82599_MAX_TX_QUEUES 128
42758cc3dcSJack F Vogel #define IXGBE_82599_MAX_RX_QUEUES 128
43758cc3dcSJack F Vogel #define IXGBE_82599_RAR_ENTRIES   128
44758cc3dcSJack F Vogel #define IXGBE_82599_MC_TBL_SIZE   128
45758cc3dcSJack F Vogel #define IXGBE_82599_VFT_TBL_SIZE  128
46758cc3dcSJack F Vogel #define IXGBE_82599_RX_PB_SIZE	  512
47758cc3dcSJack F Vogel 
482969bf0eSJack F Vogel static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
49770e416bSJack F Vogel 					 ixgbe_link_speed speed,
50770e416bSJack F Vogel 					 bool autoneg_wait_to_complete);
51d8602bb9SJack F Vogel static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
5285d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
5385d0a26eSJack F Vogel 				   u16 offset, u16 *data);
5485d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
5585d0a26eSJack F Vogel 					  u16 words, u16 *data);
56758cc3dcSJack F Vogel static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
57758cc3dcSJack F Vogel 					u8 dev_addr, u8 *data);
58758cc3dcSJack F Vogel static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
59758cc3dcSJack F Vogel 					u8 dev_addr, u8 data);
600ecc2ff0SJack F Vogel 
ixgbe_init_mac_link_ops_82599(struct ixgbe_hw * hw)61770e416bSJack F Vogel void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
62770e416bSJack F Vogel {
63770e416bSJack F Vogel 	struct ixgbe_mac_info *mac = &hw->mac;
64770e416bSJack F Vogel 
65770e416bSJack F Vogel 	DEBUGFUNC("ixgbe_init_mac_link_ops_82599");
66770e416bSJack F Vogel 
670ecc2ff0SJack F Vogel 	/*
680ecc2ff0SJack F Vogel 	 * enable the laser control functions for SFP+ fiber
690ecc2ff0SJack F Vogel 	 * and MNG not enabled
700ecc2ff0SJack F Vogel 	 */
710ecc2ff0SJack F Vogel 	if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
72758cc3dcSJack F Vogel 	    !ixgbe_mng_enabled(hw)) {
731a4e3449SJack F Vogel 		mac->ops.disable_tx_laser =
74758cc3dcSJack F Vogel 				       ixgbe_disable_tx_laser_multispeed_fiber;
751a4e3449SJack F Vogel 		mac->ops.enable_tx_laser =
76758cc3dcSJack F Vogel 					ixgbe_enable_tx_laser_multispeed_fiber;
77758cc3dcSJack F Vogel 		mac->ops.flap_tx_laser = ixgbe_flap_tx_laser_multispeed_fiber;
781a4e3449SJack F Vogel 
791a4e3449SJack F Vogel 	} else {
801a4e3449SJack F Vogel 		mac->ops.disable_tx_laser = NULL;
811a4e3449SJack F Vogel 		mac->ops.enable_tx_laser = NULL;
821a4e3449SJack F Vogel 		mac->ops.flap_tx_laser = NULL;
831a4e3449SJack F Vogel 	}
841a4e3449SJack F Vogel 
85770e416bSJack F Vogel 	if (hw->phy.multispeed_fiber) {
86770e416bSJack F Vogel 		/* Set up dual speed SFP+ support */
87758cc3dcSJack F Vogel 		mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
88758cc3dcSJack F Vogel 		mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599;
89758cc3dcSJack F Vogel 		mac->ops.set_rate_select_speed =
90758cc3dcSJack F Vogel 					       ixgbe_set_hard_rate_select_speed;
91758cc3dcSJack F Vogel 		if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber_fixed)
92758cc3dcSJack F Vogel 			mac->ops.set_rate_select_speed =
93758cc3dcSJack F Vogel 					       ixgbe_set_soft_rate_select_speed;
94770e416bSJack F Vogel 	} else {
952969bf0eSJack F Vogel 		if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) &&
962969bf0eSJack F Vogel 		     (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
97182b3808SJack F Vogel 		      hw->phy.smart_speed == ixgbe_smart_speed_on) &&
98182b3808SJack F Vogel 		      !ixgbe_verify_lesm_fw_enabled_82599(hw)) {
99758cc3dcSJack F Vogel 			mac->ops.setup_link = ixgbe_setup_mac_link_smartspeed;
1001a4e3449SJack F Vogel 		} else {
101758cc3dcSJack F Vogel 			mac->ops.setup_link = ixgbe_setup_mac_link_82599;
102770e416bSJack F Vogel 		}
103770e416bSJack F Vogel 	}
1041a4e3449SJack F Vogel }
105770e416bSJack F Vogel 
106770e416bSJack F Vogel /**
107770e416bSJack F Vogel  * ixgbe_init_phy_ops_82599 - PHY/SFP specific init
108770e416bSJack F Vogel  * @hw: pointer to hardware structure
109770e416bSJack F Vogel  *
110770e416bSJack F Vogel  * Initialize any function pointers that were not able to be
111770e416bSJack F Vogel  * set during init_shared_code because the PHY/SFP type was
112770e416bSJack F Vogel  * not known.  Perform the SFP init if necessary.
113770e416bSJack F Vogel  *
114770e416bSJack F Vogel  **/
ixgbe_init_phy_ops_82599(struct ixgbe_hw * hw)115770e416bSJack F Vogel s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
116770e416bSJack F Vogel {
117770e416bSJack F Vogel 	struct ixgbe_mac_info *mac = &hw->mac;
118770e416bSJack F Vogel 	struct ixgbe_phy_info *phy = &hw->phy;
119770e416bSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
120758cc3dcSJack F Vogel 	u32 esdp;
121770e416bSJack F Vogel 
122770e416bSJack F Vogel 	DEBUGFUNC("ixgbe_init_phy_ops_82599");
123770e416bSJack F Vogel 
124758cc3dcSJack F Vogel 	if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
125758cc3dcSJack F Vogel 		/* Store flag indicating I2C bus access control unit. */
12679b36ec9SKevin Bowling 		hw->phy.qsfp_shared_i2c_bus = true;
127758cc3dcSJack F Vogel 
128758cc3dcSJack F Vogel 		/* Initialize access to QSFP+ I2C bus */
129758cc3dcSJack F Vogel 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
130758cc3dcSJack F Vogel 		esdp |= IXGBE_ESDP_SDP0_DIR;
131758cc3dcSJack F Vogel 		esdp &= ~IXGBE_ESDP_SDP1_DIR;
132758cc3dcSJack F Vogel 		esdp &= ~IXGBE_ESDP_SDP0;
133758cc3dcSJack F Vogel 		esdp &= ~IXGBE_ESDP_SDP0_NATIVE;
134758cc3dcSJack F Vogel 		esdp &= ~IXGBE_ESDP_SDP1_NATIVE;
135758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
136758cc3dcSJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
137758cc3dcSJack F Vogel 
138758cc3dcSJack F Vogel 		phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_82599;
139758cc3dcSJack F Vogel 		phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_82599;
140758cc3dcSJack F Vogel 	}
141770e416bSJack F Vogel 	/* Identify the PHY or SFP module */
142770e416bSJack F Vogel 	ret_val = phy->ops.identify(hw);
143770e416bSJack F Vogel 	if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
144770e416bSJack F Vogel 		goto init_phy_ops_out;
145770e416bSJack F Vogel 
146770e416bSJack F Vogel 	/* Setup function pointers based on detected SFP module and speeds */
147770e416bSJack F Vogel 	ixgbe_init_mac_link_ops_82599(hw);
148770e416bSJack F Vogel 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown)
149770e416bSJack F Vogel 		hw->phy.ops.reset = NULL;
150770e416bSJack F Vogel 
151770e416bSJack F Vogel 	/* If copper media, overwrite with copper function pointers */
152770e416bSJack F Vogel 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
153758cc3dcSJack F Vogel 		mac->ops.setup_link = ixgbe_setup_copper_link_82599;
154770e416bSJack F Vogel 		mac->ops.get_link_capabilities =
155758cc3dcSJack F Vogel 				  ixgbe_get_copper_link_capabilities_generic;
156770e416bSJack F Vogel 	}
157770e416bSJack F Vogel 
158758cc3dcSJack F Vogel 	/* Set necessary function pointers based on PHY type */
159770e416bSJack F Vogel 	switch (hw->phy.type) {
160770e416bSJack F Vogel 	case ixgbe_phy_tn:
161758cc3dcSJack F Vogel 		phy->ops.setup_link = ixgbe_setup_phy_link_tnx;
162758cc3dcSJack F Vogel 		phy->ops.check_link = ixgbe_check_phy_link_tnx;
163770e416bSJack F Vogel 		phy->ops.get_firmware_version =
164758cc3dcSJack F Vogel 			     ixgbe_get_phy_firmware_version_tnx;
165770e416bSJack F Vogel 		break;
166770e416bSJack F Vogel 	default:
167770e416bSJack F Vogel 		break;
168770e416bSJack F Vogel 	}
169770e416bSJack F Vogel init_phy_ops_out:
170770e416bSJack F Vogel 	return ret_val;
171770e416bSJack F Vogel }
172770e416bSJack F Vogel 
ixgbe_setup_sfp_modules_82599(struct ixgbe_hw * hw)173770e416bSJack F Vogel s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
174770e416bSJack F Vogel {
175770e416bSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
176770e416bSJack F Vogel 	u16 list_offset, data_offset, data_value;
177770e416bSJack F Vogel 
178770e416bSJack F Vogel 	DEBUGFUNC("ixgbe_setup_sfp_modules_82599");
179770e416bSJack F Vogel 
180770e416bSJack F Vogel 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
181770e416bSJack F Vogel 		ixgbe_init_mac_link_ops_82599(hw);
182770e416bSJack F Vogel 
183770e416bSJack F Vogel 		hw->phy.ops.reset = NULL;
184770e416bSJack F Vogel 
185770e416bSJack F Vogel 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
186770e416bSJack F Vogel 							      &data_offset);
187770e416bSJack F Vogel 		if (ret_val != IXGBE_SUCCESS)
188770e416bSJack F Vogel 			goto setup_sfp_out;
189770e416bSJack F Vogel 
190d8602bb9SJack F Vogel 		/* PHY config will finish before releasing the semaphore */
19185d0a26eSJack F Vogel 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
19285d0a26eSJack F Vogel 							IXGBE_GSSR_MAC_CSR_SM);
193d8602bb9SJack F Vogel 		if (ret_val != IXGBE_SUCCESS) {
194d8602bb9SJack F Vogel 			ret_val = IXGBE_ERR_SWFW_SYNC;
195d8602bb9SJack F Vogel 			goto setup_sfp_out;
196d8602bb9SJack F Vogel 		}
197d8602bb9SJack F Vogel 
198fd75b91dSJack F Vogel 		if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
199fd75b91dSJack F Vogel 			goto setup_sfp_err;
200770e416bSJack F Vogel 		while (data_value != 0xffff) {
201770e416bSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
202770e416bSJack F Vogel 			IXGBE_WRITE_FLUSH(hw);
203fd75b91dSJack F Vogel 			if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
204fd75b91dSJack F Vogel 				goto setup_sfp_err;
205770e416bSJack F Vogel 		}
206d8602bb9SJack F Vogel 
207d8602bb9SJack F Vogel 		/* Release the semaphore */
20885d0a26eSJack F Vogel 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
209758cc3dcSJack F Vogel 		/* Delay obtaining semaphore again to allow FW access
210758cc3dcSJack F Vogel 		 * prot_autoc_write uses the semaphore too.
211758cc3dcSJack F Vogel 		 */
212d8602bb9SJack F Vogel 		msec_delay(hw->eeprom.semaphore_delay);
2131a4e3449SJack F Vogel 
2140ecc2ff0SJack F Vogel 		/* Restart DSP and set SFI mode */
215758cc3dcSJack F Vogel 		ret_val = hw->mac.ops.prot_autoc_write(hw,
216758cc3dcSJack F Vogel 			hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL,
21779b36ec9SKevin Bowling 			false);
2180ecc2ff0SJack F Vogel 
2190ecc2ff0SJack F Vogel 		if (ret_val) {
2201a4e3449SJack F Vogel 			DEBUGOUT("sfp module setup not complete\n");
2211a4e3449SJack F Vogel 			ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
2221a4e3449SJack F Vogel 			goto setup_sfp_out;
2231a4e3449SJack F Vogel 		}
2241a4e3449SJack F Vogel 
225770e416bSJack F Vogel 	}
226770e416bSJack F Vogel 
227770e416bSJack F Vogel setup_sfp_out:
228770e416bSJack F Vogel 	return ret_val;
229fd75b91dSJack F Vogel 
230fd75b91dSJack F Vogel setup_sfp_err:
231fd75b91dSJack F Vogel 	/* Release the semaphore */
232fd75b91dSJack F Vogel 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
233fd75b91dSJack F Vogel 	/* Delay obtaining semaphore again to allow FW access */
234fd75b91dSJack F Vogel 	msec_delay(hw->eeprom.semaphore_delay);
235fd75b91dSJack F Vogel 	ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
236fd75b91dSJack F Vogel 		      "eeprom read at offset %d failed", data_offset);
237fd75b91dSJack F Vogel 	return IXGBE_ERR_PHY;
238770e416bSJack F Vogel }
239770e416bSJack F Vogel 
240770e416bSJack F Vogel /**
241758cc3dcSJack F Vogel  * prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read
242758cc3dcSJack F Vogel  * @hw: pointer to hardware structure
243758cc3dcSJack F Vogel  * @locked: Return the if we locked for this read.
244758cc3dcSJack F Vogel  * @reg_val: Value we read from AUTOC
245758cc3dcSJack F Vogel  *
246758cc3dcSJack F Vogel  * For this part (82599) we need to wrap read-modify-writes with a possible
247758cc3dcSJack F Vogel  * FW/SW lock.  It is assumed this lock will be freed with the next
248758cc3dcSJack F Vogel  * prot_autoc_write_82599().
249758cc3dcSJack F Vogel  */
prot_autoc_read_82599(struct ixgbe_hw * hw,bool * locked,u32 * reg_val)250758cc3dcSJack F Vogel s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked, u32 *reg_val)
251758cc3dcSJack F Vogel {
252758cc3dcSJack F Vogel 	s32 ret_val;
253758cc3dcSJack F Vogel 
25479b36ec9SKevin Bowling 	*locked = false;
255758cc3dcSJack F Vogel 	 /* If LESM is on then we need to hold the SW/FW semaphore. */
256758cc3dcSJack F Vogel 	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
257758cc3dcSJack F Vogel 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
258758cc3dcSJack F Vogel 					IXGBE_GSSR_MAC_CSR_SM);
259758cc3dcSJack F Vogel 		if (ret_val != IXGBE_SUCCESS)
260758cc3dcSJack F Vogel 			return IXGBE_ERR_SWFW_SYNC;
261758cc3dcSJack F Vogel 
26279b36ec9SKevin Bowling 		*locked = true;
263758cc3dcSJack F Vogel 	}
264758cc3dcSJack F Vogel 
265758cc3dcSJack F Vogel 	*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
266758cc3dcSJack F Vogel 	return IXGBE_SUCCESS;
267758cc3dcSJack F Vogel }
268758cc3dcSJack F Vogel 
269758cc3dcSJack F Vogel /**
270758cc3dcSJack F Vogel  * prot_autoc_write_82599 - Hides MAC differences needed for AUTOC write
271758cc3dcSJack F Vogel  * @hw: pointer to hardware structure
2727d48aa4cSEric Joyner  * @autoc: value to write to AUTOC
273758cc3dcSJack F Vogel  * @locked: bool to indicate whether the SW/FW lock was already taken by
274758cc3dcSJack F Vogel  *          previous proc_autoc_read_82599.
275758cc3dcSJack F Vogel  *
276758cc3dcSJack F Vogel  * This part (82599) may need to hold the SW/FW lock around all writes to
277758cc3dcSJack F Vogel  * AUTOC. Likewise after a write we need to do a pipeline reset.
278758cc3dcSJack F Vogel  */
prot_autoc_write_82599(struct ixgbe_hw * hw,u32 autoc,bool locked)279758cc3dcSJack F Vogel s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 autoc, bool locked)
280758cc3dcSJack F Vogel {
281758cc3dcSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
282758cc3dcSJack F Vogel 
283758cc3dcSJack F Vogel 	/* Blocked by MNG FW so bail */
284758cc3dcSJack F Vogel 	if (ixgbe_check_reset_blocked(hw))
285758cc3dcSJack F Vogel 		goto out;
286758cc3dcSJack F Vogel 
287758cc3dcSJack F Vogel 	/* We only need to get the lock if:
288758cc3dcSJack F Vogel 	 *  - We didn't do it already (in the read part of a read-modify-write)
289758cc3dcSJack F Vogel 	 *  - LESM is enabled.
290758cc3dcSJack F Vogel 	 */
291758cc3dcSJack F Vogel 	if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) {
292758cc3dcSJack F Vogel 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
293758cc3dcSJack F Vogel 					IXGBE_GSSR_MAC_CSR_SM);
294758cc3dcSJack F Vogel 		if (ret_val != IXGBE_SUCCESS)
295758cc3dcSJack F Vogel 			return IXGBE_ERR_SWFW_SYNC;
296758cc3dcSJack F Vogel 
29779b36ec9SKevin Bowling 		locked = true;
298758cc3dcSJack F Vogel 	}
299758cc3dcSJack F Vogel 
300758cc3dcSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
301758cc3dcSJack F Vogel 	ret_val = ixgbe_reset_pipeline_82599(hw);
302758cc3dcSJack F Vogel 
303758cc3dcSJack F Vogel out:
304758cc3dcSJack F Vogel 	/* Free the SW/FW semaphore as we either grabbed it here or
305758cc3dcSJack F Vogel 	 * already had it when this function was called.
306758cc3dcSJack F Vogel 	 */
307758cc3dcSJack F Vogel 	if (locked)
308758cc3dcSJack F Vogel 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
309758cc3dcSJack F Vogel 
310758cc3dcSJack F Vogel 	return ret_val;
311758cc3dcSJack F Vogel }
312758cc3dcSJack F Vogel 
313758cc3dcSJack F Vogel /**
314770e416bSJack F Vogel  * ixgbe_init_ops_82599 - Inits func ptrs and MAC type
315770e416bSJack F Vogel  * @hw: pointer to hardware structure
316770e416bSJack F Vogel  *
317770e416bSJack F Vogel  * Initialize the function pointers and assign the MAC type for 82599.
318770e416bSJack F Vogel  * Does not touch the hardware.
319770e416bSJack F Vogel  **/
320770e416bSJack F Vogel 
ixgbe_init_ops_82599(struct ixgbe_hw * hw)321770e416bSJack F Vogel s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
322770e416bSJack F Vogel {
323770e416bSJack F Vogel 	struct ixgbe_mac_info *mac = &hw->mac;
324770e416bSJack F Vogel 	struct ixgbe_phy_info *phy = &hw->phy;
32585d0a26eSJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
326770e416bSJack F Vogel 	s32 ret_val;
3277234c309SJakub Chylkowski 	u16 i;
328770e416bSJack F Vogel 
3292969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_ops_82599");
3302969bf0eSJack F Vogel 
3310ecc2ff0SJack F Vogel 	ixgbe_init_phy_ops_generic(hw);
332770e416bSJack F Vogel 	ret_val = ixgbe_init_ops_generic(hw);
333770e416bSJack F Vogel 
334770e416bSJack F Vogel 	/* PHY */
335758cc3dcSJack F Vogel 	phy->ops.identify = ixgbe_identify_phy_82599;
336758cc3dcSJack F Vogel 	phy->ops.init = ixgbe_init_phy_ops_82599;
337770e416bSJack F Vogel 
338770e416bSJack F Vogel 	/* MAC */
339758cc3dcSJack F Vogel 	mac->ops.reset_hw = ixgbe_reset_hw_82599;
340758cc3dcSJack F Vogel 	mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_gen2;
341758cc3dcSJack F Vogel 	mac->ops.get_media_type = ixgbe_get_media_type_82599;
342770e416bSJack F Vogel 	mac->ops.get_supported_physical_layer =
343758cc3dcSJack F Vogel 				    ixgbe_get_supported_physical_layer_82599;
344758cc3dcSJack F Vogel 	mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic;
345758cc3dcSJack F Vogel 	mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic;
346758cc3dcSJack F Vogel 	mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_82599;
347758cc3dcSJack F Vogel 	mac->ops.read_analog_reg8 = ixgbe_read_analog_reg8_82599;
348758cc3dcSJack F Vogel 	mac->ops.write_analog_reg8 = ixgbe_write_analog_reg8_82599;
349758cc3dcSJack F Vogel 	mac->ops.start_hw = ixgbe_start_hw_82599;
350758cc3dcSJack F Vogel 	mac->ops.get_san_mac_addr = ixgbe_get_san_mac_addr_generic;
351758cc3dcSJack F Vogel 	mac->ops.set_san_mac_addr = ixgbe_set_san_mac_addr_generic;
352758cc3dcSJack F Vogel 	mac->ops.get_device_caps = ixgbe_get_device_caps_generic;
353758cc3dcSJack F Vogel 	mac->ops.get_wwn_prefix = ixgbe_get_wwn_prefix_generic;
354758cc3dcSJack F Vogel 	mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic;
355758cc3dcSJack F Vogel 	mac->ops.prot_autoc_read = prot_autoc_read_82599;
356758cc3dcSJack F Vogel 	mac->ops.prot_autoc_write = prot_autoc_write_82599;
357770e416bSJack F Vogel 
358770e416bSJack F Vogel 	/* RAR, Multicast, VLAN */
359758cc3dcSJack F Vogel 	mac->ops.set_vmdq = ixgbe_set_vmdq_generic;
360758cc3dcSJack F Vogel 	mac->ops.set_vmdq_san_mac = ixgbe_set_vmdq_san_mac_generic;
361758cc3dcSJack F Vogel 	mac->ops.clear_vmdq = ixgbe_clear_vmdq_generic;
362758cc3dcSJack F Vogel 	mac->ops.insert_mac_addr = ixgbe_insert_mac_addr_generic;
363770e416bSJack F Vogel 	mac->rar_highwater = 1;
364758cc3dcSJack F Vogel 	mac->ops.set_vfta = ixgbe_set_vfta_generic;
365758cc3dcSJack F Vogel 	mac->ops.set_vlvf = ixgbe_set_vlvf_generic;
366758cc3dcSJack F Vogel 	mac->ops.clear_vfta = ixgbe_clear_vfta_generic;
367758cc3dcSJack F Vogel 	mac->ops.init_uta_tables = ixgbe_init_uta_tables_generic;
368758cc3dcSJack F Vogel 	mac->ops.setup_sfp = ixgbe_setup_sfp_modules_82599;
369758cc3dcSJack F Vogel 	mac->ops.set_mac_anti_spoofing = ixgbe_set_mac_anti_spoofing;
370758cc3dcSJack F Vogel 	mac->ops.set_vlan_anti_spoofing = ixgbe_set_vlan_anti_spoofing;
371770e416bSJack F Vogel 
372770e416bSJack F Vogel 	/* Link */
373758cc3dcSJack F Vogel 	mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82599;
374758cc3dcSJack F Vogel 	mac->ops.check_link = ixgbe_check_mac_link_generic;
375758cc3dcSJack F Vogel 	mac->ops.setup_rxpba = ixgbe_set_rxpba_generic;
376770e416bSJack F Vogel 	ixgbe_init_mac_link_ops_82599(hw);
377770e416bSJack F Vogel 
378758cc3dcSJack F Vogel 	mac->mcft_size		= IXGBE_82599_MC_TBL_SIZE;
379758cc3dcSJack F Vogel 	mac->vft_size		= IXGBE_82599_VFT_TBL_SIZE;
380758cc3dcSJack F Vogel 	mac->num_rar_entries	= IXGBE_82599_RAR_ENTRIES;
381758cc3dcSJack F Vogel 	mac->rx_pb_size		= IXGBE_82599_RX_PB_SIZE;
382758cc3dcSJack F Vogel 	mac->max_rx_queues	= IXGBE_82599_MAX_RX_QUEUES;
383758cc3dcSJack F Vogel 	mac->max_tx_queues	= IXGBE_82599_MAX_TX_QUEUES;
3842969bf0eSJack F Vogel 	mac->max_msix_vectors	= ixgbe_get_pcie_msix_count_generic(hw);
385770e416bSJack F Vogel 
386a9ca1c79SSean Bruno 	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
387a9ca1c79SSean Bruno 				      & IXGBE_FWSM_MODE_MASK);
38885d0a26eSJack F Vogel 
3897234c309SJakub Chylkowski 	for (i = 0; i < 64; i++)
3907234c309SJakub Chylkowski 		hw->mbx.ops[i].init_params = ixgbe_init_mbx_params_pf;
391d8602bb9SJack F Vogel 
39285d0a26eSJack F Vogel 	/* EEPROM */
393758cc3dcSJack F Vogel 	eeprom->ops.read = ixgbe_read_eeprom_82599;
394758cc3dcSJack F Vogel 	eeprom->ops.read_buffer = ixgbe_read_eeprom_buffer_82599;
39585d0a26eSJack F Vogel 
39685d0a26eSJack F Vogel 	/* Manageability interface */
397758cc3dcSJack F Vogel 	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic;
39885d0a26eSJack F Vogel 
3993f66b96dSKevin Bowling 	mac->ops.get_thermal_sensor_data =
4003f66b96dSKevin Bowling 				    ixgbe_get_thermal_sensor_data_generic;
4013f66b96dSKevin Bowling 	mac->ops.init_thermal_sensor_thresh =
4023f66b96dSKevin Bowling 				    ixgbe_init_thermal_sensor_thresh_generic;
4033f66b96dSKevin Bowling 
4048eb6488eSEric Joyner 	mac->ops.bypass_rw = ixgbe_bypass_rw_generic;
4058eb6488eSEric Joyner 	mac->ops.bypass_valid_rd = ixgbe_bypass_valid_rd_generic;
4068eb6488eSEric Joyner 	mac->ops.bypass_set = ixgbe_bypass_set_generic;
4078eb6488eSEric Joyner 	mac->ops.bypass_rd_eep = ixgbe_bypass_rd_eep_generic;
40885d0a26eSJack F Vogel 
409758cc3dcSJack F Vogel 	mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
410fd75b91dSJack F Vogel 
411770e416bSJack F Vogel 	return ret_val;
412770e416bSJack F Vogel }
413770e416bSJack F Vogel 
414770e416bSJack F Vogel /**
415770e416bSJack F Vogel  * ixgbe_get_link_capabilities_82599 - Determines link capabilities
416770e416bSJack F Vogel  * @hw: pointer to hardware structure
417770e416bSJack F Vogel  * @speed: pointer to link speed
41879b36ec9SKevin Bowling  * @autoneg: true when autoneg or autotry is enabled
419770e416bSJack F Vogel  *
420770e416bSJack F Vogel  * Determines the link capabilities by reading the AUTOC register.
421770e416bSJack F Vogel  **/
ixgbe_get_link_capabilities_82599(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)422770e416bSJack F Vogel s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
423770e416bSJack F Vogel 				      ixgbe_link_speed *speed,
4240ecc2ff0SJack F Vogel 				      bool *autoneg)
425770e416bSJack F Vogel {
426770e416bSJack F Vogel 	s32 status = IXGBE_SUCCESS;
427770e416bSJack F Vogel 	u32 autoc = 0;
428770e416bSJack F Vogel 
4292969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_link_capabilities_82599");
4302969bf0eSJack F Vogel 
431c0014855SJack F Vogel 
4321a4e3449SJack F Vogel 	/* Check if 1G SFP module. */
4331a4e3449SJack F Vogel 	if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
434a621e3c8SJack F Vogel 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
4356f37f232SEric Joyner 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
4366f37f232SEric Joyner 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
437a621e3c8SJack F Vogel 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
438*89d40969STore Amundsen 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
439*89d40969STore Amundsen 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core0 ||
440*89d40969STore Amundsen 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1) {
4411a4e3449SJack F Vogel 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
44279b36ec9SKevin Bowling 		*autoneg = true;
4431a4e3449SJack F Vogel 		goto out;
4441a4e3449SJack F Vogel 	}
445c0014855SJack F Vogel 
44648ddd1b9SKevin Bowling 	if (hw->phy.sfp_type == ixgbe_sfp_type_da_cu_core0 ||
44748ddd1b9SKevin Bowling 	    hw->phy.sfp_type == ixgbe_sfp_type_da_cu_core1) {
44848ddd1b9SKevin Bowling 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
44948ddd1b9SKevin Bowling 		*autoneg = true;
45048ddd1b9SKevin Bowling 
45148ddd1b9SKevin Bowling 		if (hw->phy.multispeed_fiber)
45248ddd1b9SKevin Bowling 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
45348ddd1b9SKevin Bowling 
45448ddd1b9SKevin Bowling 		goto out;
45548ddd1b9SKevin Bowling 	}
45648ddd1b9SKevin Bowling 
457770e416bSJack F Vogel 	/*
458770e416bSJack F Vogel 	 * Determine link capabilities based on the stored value of AUTOC,
459770e416bSJack F Vogel 	 * which represents EEPROM defaults.  If AUTOC value has not
460770e416bSJack F Vogel 	 * been stored, use the current register values.
461770e416bSJack F Vogel 	 */
462770e416bSJack F Vogel 	if (hw->mac.orig_link_settings_stored)
463770e416bSJack F Vogel 		autoc = hw->mac.orig_autoc;
464770e416bSJack F Vogel 	else
465770e416bSJack F Vogel 		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
466770e416bSJack F Vogel 
467770e416bSJack F Vogel 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
468770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
469770e416bSJack F Vogel 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
47079b36ec9SKevin Bowling 		*autoneg = false;
471770e416bSJack F Vogel 		break;
472770e416bSJack F Vogel 
473770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
474770e416bSJack F Vogel 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
47579b36ec9SKevin Bowling 		*autoneg = false;
476770e416bSJack F Vogel 		break;
477770e416bSJack F Vogel 
478770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_1G_AN:
479770e416bSJack F Vogel 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
48079b36ec9SKevin Bowling 		*autoneg = true;
481770e416bSJack F Vogel 		break;
482770e416bSJack F Vogel 
483770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_10G_SERIAL:
484770e416bSJack F Vogel 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
48579b36ec9SKevin Bowling 		*autoneg = false;
486770e416bSJack F Vogel 		break;
487770e416bSJack F Vogel 
488770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
489770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
490770e416bSJack F Vogel 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
491770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KR_SUPP)
492770e416bSJack F Vogel 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
493770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
494770e416bSJack F Vogel 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
495770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KX_SUPP)
496770e416bSJack F Vogel 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
49779b36ec9SKevin Bowling 		*autoneg = true;
498770e416bSJack F Vogel 		break;
499770e416bSJack F Vogel 
500770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII:
501770e416bSJack F Vogel 		*speed = IXGBE_LINK_SPEED_100_FULL;
502770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KR_SUPP)
503770e416bSJack F Vogel 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
504770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
505770e416bSJack F Vogel 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
506770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KX_SUPP)
507770e416bSJack F Vogel 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
50879b36ec9SKevin Bowling 		*autoneg = true;
509770e416bSJack F Vogel 		break;
510770e416bSJack F Vogel 
511770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_SGMII_1G_100M:
512770e416bSJack F Vogel 		*speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL;
51379b36ec9SKevin Bowling 		*autoneg = false;
514770e416bSJack F Vogel 		break;
515770e416bSJack F Vogel 
516770e416bSJack F Vogel 	default:
517770e416bSJack F Vogel 		status = IXGBE_ERR_LINK_SETUP;
518770e416bSJack F Vogel 		goto out;
519770e416bSJack F Vogel 		break;
520770e416bSJack F Vogel 	}
521770e416bSJack F Vogel 
522770e416bSJack F Vogel 	if (hw->phy.multispeed_fiber) {
523770e416bSJack F Vogel 		*speed |= IXGBE_LINK_SPEED_10GB_FULL |
524770e416bSJack F Vogel 			  IXGBE_LINK_SPEED_1GB_FULL;
525758cc3dcSJack F Vogel 
526758cc3dcSJack F Vogel 		/* QSFP must not enable full auto-negotiation
527758cc3dcSJack F Vogel 		 * Limited autoneg is enabled at 1G
528758cc3dcSJack F Vogel 		 */
529758cc3dcSJack F Vogel 		if (hw->phy.media_type == ixgbe_media_type_fiber_qsfp)
53079b36ec9SKevin Bowling 			*autoneg = false;
531758cc3dcSJack F Vogel 		else
53279b36ec9SKevin Bowling 			*autoneg = true;
533770e416bSJack F Vogel 	}
534770e416bSJack F Vogel 
535770e416bSJack F Vogel out:
536770e416bSJack F Vogel 	return status;
537770e416bSJack F Vogel }
538770e416bSJack F Vogel 
539770e416bSJack F Vogel /**
540770e416bSJack F Vogel  * ixgbe_get_media_type_82599 - Get media type
541770e416bSJack F Vogel  * @hw: pointer to hardware structure
542770e416bSJack F Vogel  *
543770e416bSJack F Vogel  * Returns the media type (fiber, copper, backplane)
544770e416bSJack F Vogel  **/
ixgbe_get_media_type_82599(struct ixgbe_hw * hw)545770e416bSJack F Vogel enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
546770e416bSJack F Vogel {
547770e416bSJack F Vogel 	enum ixgbe_media_type media_type;
548770e416bSJack F Vogel 
5492969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_media_type_82599");
5502969bf0eSJack F Vogel 
551770e416bSJack F Vogel 	/* Detect if there is a copper PHY attached. */
5521a4e3449SJack F Vogel 	switch (hw->phy.type) {
5531a4e3449SJack F Vogel 	case ixgbe_phy_cu_unknown:
5541a4e3449SJack F Vogel 	case ixgbe_phy_tn:
555770e416bSJack F Vogel 		media_type = ixgbe_media_type_copper;
556770e416bSJack F Vogel 		goto out;
5571a4e3449SJack F Vogel 	default:
5581a4e3449SJack F Vogel 		break;
559770e416bSJack F Vogel 	}
560770e416bSJack F Vogel 
561770e416bSJack F Vogel 	switch (hw->device_id) {
562770e416bSJack F Vogel 	case IXGBE_DEV_ID_82599_KX4:
5632969bf0eSJack F Vogel 	case IXGBE_DEV_ID_82599_KX4_MEZZ:
5642969bf0eSJack F Vogel 	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
56585d0a26eSJack F Vogel 	case IXGBE_DEV_ID_82599_KR:
5661a4e3449SJack F Vogel 	case IXGBE_DEV_ID_82599_BACKPLANE_FCOE:
567d8602bb9SJack F Vogel 	case IXGBE_DEV_ID_82599_XAUI_LOM:
568770e416bSJack F Vogel 		/* Default device ID is mezzanine card KX/KX4 */
569770e416bSJack F Vogel 		media_type = ixgbe_media_type_backplane;
570770e416bSJack F Vogel 		break;
571770e416bSJack F Vogel 	case IXGBE_DEV_ID_82599_SFP:
5721a4e3449SJack F Vogel 	case IXGBE_DEV_ID_82599_SFP_FCOE:
57385d0a26eSJack F Vogel 	case IXGBE_DEV_ID_82599_SFP_EM:
574a621e3c8SJack F Vogel 	case IXGBE_DEV_ID_82599_SFP_SF2:
5750ecc2ff0SJack F Vogel 	case IXGBE_DEV_ID_82599_SFP_SF_QP:
57685d0a26eSJack F Vogel 	case IXGBE_DEV_ID_82599EN_SFP:
577770e416bSJack F Vogel 		media_type = ixgbe_media_type_fiber;
578770e416bSJack F Vogel 		break;
579770e416bSJack F Vogel 	case IXGBE_DEV_ID_82599_CX4:
5802969bf0eSJack F Vogel 		media_type = ixgbe_media_type_cx4;
581770e416bSJack F Vogel 		break;
5821a4e3449SJack F Vogel 	case IXGBE_DEV_ID_82599_T3_LOM:
5831a4e3449SJack F Vogel 		media_type = ixgbe_media_type_copper;
5841a4e3449SJack F Vogel 		break;
5859228ac3aSKevin Bowling 	case IXGBE_DEV_ID_82599_LS:
5869228ac3aSKevin Bowling 		media_type = ixgbe_media_type_fiber_lco;
5879228ac3aSKevin Bowling 		break;
588758cc3dcSJack F Vogel 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
589758cc3dcSJack F Vogel 		media_type = ixgbe_media_type_fiber_qsfp;
590758cc3dcSJack F Vogel 		break;
5910ecc2ff0SJack F Vogel 	case IXGBE_DEV_ID_82599_BYPASS:
5920ecc2ff0SJack F Vogel 		media_type = ixgbe_media_type_fiber_fixed;
59379b36ec9SKevin Bowling 		hw->phy.multispeed_fiber = true;
5940ecc2ff0SJack F Vogel 		break;
595770e416bSJack F Vogel 	default:
596770e416bSJack F Vogel 		media_type = ixgbe_media_type_unknown;
597770e416bSJack F Vogel 		break;
598770e416bSJack F Vogel 	}
599770e416bSJack F Vogel out:
600770e416bSJack F Vogel 	return media_type;
601770e416bSJack F Vogel }
602770e416bSJack F Vogel 
603770e416bSJack F Vogel /**
604fd75b91dSJack F Vogel  * ixgbe_stop_mac_link_on_d3_82599 - Disables link on D3
605fd75b91dSJack F Vogel  * @hw: pointer to hardware structure
606fd75b91dSJack F Vogel  *
607fd75b91dSJack F Vogel  * Disables link during D3 power down sequence.
608fd75b91dSJack F Vogel  *
609fd75b91dSJack F Vogel  **/
ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw * hw)610fd75b91dSJack F Vogel void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw)
611fd75b91dSJack F Vogel {
612fd75b91dSJack F Vogel 	u32 autoc2_reg;
613fd75b91dSJack F Vogel 	u16 ee_ctrl_2 = 0;
614fd75b91dSJack F Vogel 
615fd75b91dSJack F Vogel 	DEBUGFUNC("ixgbe_stop_mac_link_on_d3_82599");
616fd75b91dSJack F Vogel 	ixgbe_read_eeprom(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2);
617fd75b91dSJack F Vogel 
618758cc3dcSJack F Vogel 	if (!ixgbe_mng_present(hw) && !hw->wol_enabled &&
619fd75b91dSJack F Vogel 	    ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) {
620fd75b91dSJack F Vogel 		autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
621fd75b91dSJack F Vogel 		autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK;
622fd75b91dSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
623fd75b91dSJack F Vogel 	}
624fd75b91dSJack F Vogel }
625fd75b91dSJack F Vogel 
626fd75b91dSJack F Vogel /**
6272969bf0eSJack F Vogel  * ixgbe_start_mac_link_82599 - Setup MAC link settings
628770e416bSJack F Vogel  * @hw: pointer to hardware structure
62979b36ec9SKevin Bowling  * @autoneg_wait_to_complete: true when waiting for completion is needed
630770e416bSJack F Vogel  *
631770e416bSJack F Vogel  * Configures link settings based on values in the ixgbe_hw struct.
632770e416bSJack F Vogel  * Restarts the link.  Performs autonegotiation if needed.
633770e416bSJack F Vogel  **/
ixgbe_start_mac_link_82599(struct ixgbe_hw * hw,bool autoneg_wait_to_complete)6342969bf0eSJack F Vogel s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
6352969bf0eSJack F Vogel 			       bool autoneg_wait_to_complete)
636770e416bSJack F Vogel {
637770e416bSJack F Vogel 	u32 autoc_reg;
638770e416bSJack F Vogel 	u32 links_reg;
639770e416bSJack F Vogel 	u32 i;
640770e416bSJack F Vogel 	s32 status = IXGBE_SUCCESS;
64179b36ec9SKevin Bowling 	bool got_lock = false;
642770e416bSJack F Vogel 
6432969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_start_mac_link_82599");
6442969bf0eSJack F Vogel 
645d8602bb9SJack F Vogel 
6460ecc2ff0SJack F Vogel 	/*  reset_pipeline requires us to hold this lock as it writes to
6470ecc2ff0SJack F Vogel 	 *  AUTOC.
6480ecc2ff0SJack F Vogel 	 */
6490ecc2ff0SJack F Vogel 	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
6500ecc2ff0SJack F Vogel 		status = hw->mac.ops.acquire_swfw_sync(hw,
6510ecc2ff0SJack F Vogel 						       IXGBE_GSSR_MAC_CSR_SM);
6520ecc2ff0SJack F Vogel 		if (status != IXGBE_SUCCESS)
6530ecc2ff0SJack F Vogel 			goto out;
6540ecc2ff0SJack F Vogel 
65579b36ec9SKevin Bowling 		got_lock = true;
6560ecc2ff0SJack F Vogel 	}
6570ecc2ff0SJack F Vogel 
658770e416bSJack F Vogel 	/* Restart link */
6590ecc2ff0SJack F Vogel 	ixgbe_reset_pipeline_82599(hw);
6600ecc2ff0SJack F Vogel 
6610ecc2ff0SJack F Vogel 	if (got_lock)
6620ecc2ff0SJack F Vogel 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
663770e416bSJack F Vogel 
664770e416bSJack F Vogel 	/* Only poll for autoneg to complete if specified to do so */
6652969bf0eSJack F Vogel 	if (autoneg_wait_to_complete) {
6660ecc2ff0SJack F Vogel 		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
667770e416bSJack F Vogel 		if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
668770e416bSJack F Vogel 		     IXGBE_AUTOC_LMS_KX4_KX_KR ||
669770e416bSJack F Vogel 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
6701a4e3449SJack F Vogel 		     IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
6711a4e3449SJack F Vogel 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
672770e416bSJack F Vogel 		     IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
673770e416bSJack F Vogel 			links_reg = 0; /* Just in case Autoneg time = 0 */
674770e416bSJack F Vogel 			for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
675770e416bSJack F Vogel 				links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
676770e416bSJack F Vogel 				if (links_reg & IXGBE_LINKS_KX_AN_COMP)
677770e416bSJack F Vogel 					break;
678770e416bSJack F Vogel 				msec_delay(100);
679770e416bSJack F Vogel 			}
680770e416bSJack F Vogel 			if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
681770e416bSJack F Vogel 				status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
682770e416bSJack F Vogel 				DEBUGOUT("Autoneg did not complete.\n");
683770e416bSJack F Vogel 			}
684770e416bSJack F Vogel 		}
685770e416bSJack F Vogel 	}
686770e416bSJack F Vogel 
687770e416bSJack F Vogel 	/* Add delay to filter out noises during initial link setup */
688770e416bSJack F Vogel 	msec_delay(50);
689770e416bSJack F Vogel 
6900ecc2ff0SJack F Vogel out:
691770e416bSJack F Vogel 	return status;
692770e416bSJack F Vogel }
693770e416bSJack F Vogel 
694770e416bSJack F Vogel /**
6951a4e3449SJack F Vogel  * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
6961a4e3449SJack F Vogel  * @hw: pointer to hardware structure
6971a4e3449SJack F Vogel  *
6981a4e3449SJack F Vogel  * The base drivers may require better control over SFP+ module
6991a4e3449SJack F Vogel  * PHY states.  This includes selectively shutting down the Tx
7001a4e3449SJack F Vogel  * laser on the PHY, effectively halting physical link.
7011a4e3449SJack F Vogel  **/
ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)7021a4e3449SJack F Vogel void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
7031a4e3449SJack F Vogel {
7041a4e3449SJack F Vogel 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
7051a4e3449SJack F Vogel 
706758cc3dcSJack F Vogel 	/* Blocked by MNG FW so bail */
707758cc3dcSJack F Vogel 	if (ixgbe_check_reset_blocked(hw))
708758cc3dcSJack F Vogel 		return;
709758cc3dcSJack F Vogel 
710758cc3dcSJack F Vogel 	/* Disable Tx laser; allow 100us to go dark per spec */
7111a4e3449SJack F Vogel 	esdp_reg |= IXGBE_ESDP_SDP3;
7121a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
7131a4e3449SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
7141a4e3449SJack F Vogel 	usec_delay(100);
7151a4e3449SJack F Vogel }
7161a4e3449SJack F Vogel 
7171a4e3449SJack F Vogel /**
7181a4e3449SJack F Vogel  * ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser
7191a4e3449SJack F Vogel  * @hw: pointer to hardware structure
7201a4e3449SJack F Vogel  *
7211a4e3449SJack F Vogel  * The base drivers may require better control over SFP+ module
7221a4e3449SJack F Vogel  * PHY states.  This includes selectively turning on the Tx
7231a4e3449SJack F Vogel  * laser on the PHY, effectively starting physical link.
7241a4e3449SJack F Vogel  **/
ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)7251a4e3449SJack F Vogel void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
7261a4e3449SJack F Vogel {
7271a4e3449SJack F Vogel 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
7281a4e3449SJack F Vogel 
729758cc3dcSJack F Vogel 	/* Enable Tx laser; allow 100ms to light up */
7301a4e3449SJack F Vogel 	esdp_reg &= ~IXGBE_ESDP_SDP3;
7311a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
7321a4e3449SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
7331a4e3449SJack F Vogel 	msec_delay(100);
7341a4e3449SJack F Vogel }
7351a4e3449SJack F Vogel 
7361a4e3449SJack F Vogel /**
7371a4e3449SJack F Vogel  * ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
7381a4e3449SJack F Vogel  * @hw: pointer to hardware structure
7391a4e3449SJack F Vogel  *
7401a4e3449SJack F Vogel  * When the driver changes the link speeds that it can support,
74179b36ec9SKevin Bowling  * it sets autotry_restart to true to indicate that we need to
7421a4e3449SJack F Vogel  * initiate a new autotry session with the link partner.  To do
743758cc3dcSJack F Vogel  * so, we set the speed then disable and re-enable the Tx laser, to
7441a4e3449SJack F Vogel  * alert the link partner that it also needs to restart autotry on its
74579b36ec9SKevin Bowling  * end.  This is consistent with true clause 37 autoneg, which also
7461a4e3449SJack F Vogel  * involves a loss of signal.
7471a4e3449SJack F Vogel  **/
ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)7481a4e3449SJack F Vogel void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
7491a4e3449SJack F Vogel {
7501a4e3449SJack F Vogel 	DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber");
7511a4e3449SJack F Vogel 
752758cc3dcSJack F Vogel 	/* Blocked by MNG FW so bail */
753758cc3dcSJack F Vogel 	if (ixgbe_check_reset_blocked(hw))
754758cc3dcSJack F Vogel 		return;
755758cc3dcSJack F Vogel 
7561a4e3449SJack F Vogel 	if (hw->mac.autotry_restart) {
7571a4e3449SJack F Vogel 		ixgbe_disable_tx_laser_multispeed_fiber(hw);
7581a4e3449SJack F Vogel 		ixgbe_enable_tx_laser_multispeed_fiber(hw);
75979b36ec9SKevin Bowling 		hw->mac.autotry_restart = false;
7601a4e3449SJack F Vogel 	}
7611a4e3449SJack F Vogel }
7621a4e3449SJack F Vogel 
7631a4e3449SJack F Vogel /**
764758cc3dcSJack F Vogel  * ixgbe_set_hard_rate_select_speed - Set module link speed
7650ecc2ff0SJack F Vogel  * @hw: pointer to hardware structure
7660ecc2ff0SJack F Vogel  * @speed: link speed to set
7670ecc2ff0SJack F Vogel  *
768758cc3dcSJack F Vogel  * Set module link speed via RS0/RS1 rate select pins.
7690ecc2ff0SJack F Vogel  */
ixgbe_set_hard_rate_select_speed(struct ixgbe_hw * hw,ixgbe_link_speed speed)770758cc3dcSJack F Vogel void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw,
7710ecc2ff0SJack F Vogel 					ixgbe_link_speed speed)
7720ecc2ff0SJack F Vogel {
773758cc3dcSJack F Vogel 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
7740ecc2ff0SJack F Vogel 
7750ecc2ff0SJack F Vogel 	switch (speed) {
7760ecc2ff0SJack F Vogel 	case IXGBE_LINK_SPEED_10GB_FULL:
777758cc3dcSJack F Vogel 		esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
7780ecc2ff0SJack F Vogel 		break;
7790ecc2ff0SJack F Vogel 	case IXGBE_LINK_SPEED_1GB_FULL:
780758cc3dcSJack F Vogel 		esdp_reg &= ~IXGBE_ESDP_SDP5;
781758cc3dcSJack F Vogel 		esdp_reg |= IXGBE_ESDP_SDP5_DIR;
7820ecc2ff0SJack F Vogel 		break;
7830ecc2ff0SJack F Vogel 	default:
7840ecc2ff0SJack F Vogel 		DEBUGOUT("Invalid fixed module speed\n");
7850ecc2ff0SJack F Vogel 		return;
7860ecc2ff0SJack F Vogel 	}
7870ecc2ff0SJack F Vogel 
788770e416bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
7891a4e3449SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
7900ecc2ff0SJack F Vogel }
791770e416bSJack F Vogel 
7922969bf0eSJack F Vogel /**
7932969bf0eSJack F Vogel  * ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed
7942969bf0eSJack F Vogel  * @hw: pointer to hardware structure
7952969bf0eSJack F Vogel  * @speed: new link speed
79679b36ec9SKevin Bowling  * @autoneg_wait_to_complete: true when waiting for completion is needed
7972969bf0eSJack F Vogel  *
7982969bf0eSJack F Vogel  * Implements the Intel SmartSpeed algorithm.
7992969bf0eSJack F Vogel  **/
ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)8002969bf0eSJack F Vogel s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
8010ecc2ff0SJack F Vogel 				    ixgbe_link_speed speed,
8022969bf0eSJack F Vogel 				    bool autoneg_wait_to_complete)
8032969bf0eSJack F Vogel {
8042969bf0eSJack F Vogel 	s32 status = IXGBE_SUCCESS;
8051a4e3449SJack F Vogel 	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
8062969bf0eSJack F Vogel 	s32 i, j;
80779b36ec9SKevin Bowling 	bool link_up = false;
8082969bf0eSJack F Vogel 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
8092969bf0eSJack F Vogel 
8102969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_setup_mac_link_smartspeed");
8112969bf0eSJack F Vogel 
8122969bf0eSJack F Vogel 	 /* Set autoneg_advertised value based on input link speed */
8132969bf0eSJack F Vogel 	hw->phy.autoneg_advertised = 0;
8142969bf0eSJack F Vogel 
8152969bf0eSJack F Vogel 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
8162969bf0eSJack F Vogel 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
8172969bf0eSJack F Vogel 
8182969bf0eSJack F Vogel 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
8192969bf0eSJack F Vogel 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
8202969bf0eSJack F Vogel 
8212969bf0eSJack F Vogel 	if (speed & IXGBE_LINK_SPEED_100_FULL)
8222969bf0eSJack F Vogel 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
8232969bf0eSJack F Vogel 
8242969bf0eSJack F Vogel 	/*
8252969bf0eSJack F Vogel 	 * Implement Intel SmartSpeed algorithm.  SmartSpeed will reduce the
8262969bf0eSJack F Vogel 	 * autoneg advertisement if link is unable to be established at the
8272969bf0eSJack F Vogel 	 * highest negotiated rate.  This can sometimes happen due to integrity
8282969bf0eSJack F Vogel 	 * issues with the physical media connection.
8292969bf0eSJack F Vogel 	 */
8302969bf0eSJack F Vogel 
8312969bf0eSJack F Vogel 	/* First, try to get link with full advertisement */
83279b36ec9SKevin Bowling 	hw->phy.smart_speed_active = false;
8332969bf0eSJack F Vogel 	for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) {
8340ecc2ff0SJack F Vogel 		status = ixgbe_setup_mac_link_82599(hw, speed,
8352969bf0eSJack F Vogel 						    autoneg_wait_to_complete);
8362969bf0eSJack F Vogel 		if (status != IXGBE_SUCCESS)
8372969bf0eSJack F Vogel 			goto out;
8382969bf0eSJack F Vogel 
8392969bf0eSJack F Vogel 		/*
8402969bf0eSJack F Vogel 		 * Wait for the controller to acquire link.  Per IEEE 802.3ap,
8412969bf0eSJack F Vogel 		 * Section 73.10.2, we may have to wait up to 500ms if KR is
8422969bf0eSJack F Vogel 		 * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per
8432969bf0eSJack F Vogel 		 * Table 9 in the AN MAS.
8442969bf0eSJack F Vogel 		 */
8452969bf0eSJack F Vogel 		for (i = 0; i < 5; i++) {
8462969bf0eSJack F Vogel 			msec_delay(100);
8472969bf0eSJack F Vogel 
8482969bf0eSJack F Vogel 			/* If we have link, just jump out */
8492969bf0eSJack F Vogel 			status = ixgbe_check_link(hw, &link_speed, &link_up,
85079b36ec9SKevin Bowling 						  false);
8512969bf0eSJack F Vogel 			if (status != IXGBE_SUCCESS)
8522969bf0eSJack F Vogel 				goto out;
8532969bf0eSJack F Vogel 
8542969bf0eSJack F Vogel 			if (link_up)
8552969bf0eSJack F Vogel 				goto out;
8562969bf0eSJack F Vogel 		}
8572969bf0eSJack F Vogel 	}
8582969bf0eSJack F Vogel 
8592969bf0eSJack F Vogel 	/*
8602969bf0eSJack F Vogel 	 * We didn't get link.  If we advertised KR plus one of KX4/KX
8612969bf0eSJack F Vogel 	 * (or BX4/BX), then disable KR and try again.
8622969bf0eSJack F Vogel 	 */
8632969bf0eSJack F Vogel 	if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) ||
8642969bf0eSJack F Vogel 	    ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0))
8652969bf0eSJack F Vogel 		goto out;
8662969bf0eSJack F Vogel 
8672969bf0eSJack F Vogel 	/* Turn SmartSpeed on to disable KR support */
86879b36ec9SKevin Bowling 	hw->phy.smart_speed_active = true;
8690ecc2ff0SJack F Vogel 	status = ixgbe_setup_mac_link_82599(hw, speed,
8702969bf0eSJack F Vogel 					    autoneg_wait_to_complete);
8712969bf0eSJack F Vogel 	if (status != IXGBE_SUCCESS)
8722969bf0eSJack F Vogel 		goto out;
8732969bf0eSJack F Vogel 
8742969bf0eSJack F Vogel 	/*
8752969bf0eSJack F Vogel 	 * Wait for the controller to acquire link.  600ms will allow for
8762969bf0eSJack F Vogel 	 * the AN link_fail_inhibit_timer as well for multiple cycles of
8772969bf0eSJack F Vogel 	 * parallel detect, both 10g and 1g. This allows for the maximum
8782969bf0eSJack F Vogel 	 * connect attempts as defined in the AN MAS table 73-7.
8792969bf0eSJack F Vogel 	 */
8802969bf0eSJack F Vogel 	for (i = 0; i < 6; i++) {
8812969bf0eSJack F Vogel 		msec_delay(100);
8822969bf0eSJack F Vogel 
8832969bf0eSJack F Vogel 		/* If we have link, just jump out */
88479b36ec9SKevin Bowling 		status = ixgbe_check_link(hw, &link_speed, &link_up, false);
8852969bf0eSJack F Vogel 		if (status != IXGBE_SUCCESS)
8862969bf0eSJack F Vogel 			goto out;
8872969bf0eSJack F Vogel 
8882969bf0eSJack F Vogel 		if (link_up)
8892969bf0eSJack F Vogel 			goto out;
8902969bf0eSJack F Vogel 	}
8912969bf0eSJack F Vogel 
8922969bf0eSJack F Vogel 	/* We didn't get link.  Turn SmartSpeed back off. */
89379b36ec9SKevin Bowling 	hw->phy.smart_speed_active = false;
8940ecc2ff0SJack F Vogel 	status = ixgbe_setup_mac_link_82599(hw, speed,
8952969bf0eSJack F Vogel 					    autoneg_wait_to_complete);
8962969bf0eSJack F Vogel 
8972969bf0eSJack F Vogel out:
8981a4e3449SJack F Vogel 	if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
8991a4e3449SJack F Vogel 		DEBUGOUT("Smartspeed has downgraded the link speed "
9001a4e3449SJack F Vogel 		"from the maximum advertised\n");
901770e416bSJack F Vogel 	return status;
902770e416bSJack F Vogel }
903770e416bSJack F Vogel 
904770e416bSJack F Vogel /**
9052969bf0eSJack F Vogel  * ixgbe_setup_mac_link_82599 - Set MAC link speed
906770e416bSJack F Vogel  * @hw: pointer to hardware structure
907770e416bSJack F Vogel  * @speed: new link speed
90879b36ec9SKevin Bowling  * @autoneg_wait_to_complete: true when waiting for completion is needed
909770e416bSJack F Vogel  *
910770e416bSJack F Vogel  * Set the link speed in the AUTOC register and restarts link.
911770e416bSJack F Vogel  **/
ixgbe_setup_mac_link_82599(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)9122969bf0eSJack F Vogel s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
9130ecc2ff0SJack F Vogel 			       ixgbe_link_speed speed,
914770e416bSJack F Vogel 			       bool autoneg_wait_to_complete)
915770e416bSJack F Vogel {
91679b36ec9SKevin Bowling 	bool autoneg = false;
917770e416bSJack F Vogel 	s32 status = IXGBE_SUCCESS;
918758cc3dcSJack F Vogel 	u32 pma_pmd_1g, link_mode;
919758cc3dcSJack F Vogel 	u32 current_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); /* holds the value of AUTOC register at this current point in time */
920758cc3dcSJack F Vogel 	u32 orig_autoc = 0; /* holds the cached value of AUTOC register */
921758cc3dcSJack F Vogel 	u32 autoc = current_autoc; /* Temporary variable used for comparison purposes */
922770e416bSJack F Vogel 	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
923770e416bSJack F Vogel 	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
924770e416bSJack F Vogel 	u32 links_reg;
925770e416bSJack F Vogel 	u32 i;
926770e416bSJack F Vogel 	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
927770e416bSJack F Vogel 
9282969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_setup_mac_link_82599");
9292969bf0eSJack F Vogel 
930770e416bSJack F Vogel 	/* Check to see if speed passed in is supported. */
931770e416bSJack F Vogel 	status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg);
9320ecc2ff0SJack F Vogel 	if (status)
933770e416bSJack F Vogel 		goto out;
934770e416bSJack F Vogel 
935770e416bSJack F Vogel 	speed &= link_capabilities;
936770e416bSJack F Vogel 
937d8602bb9SJack F Vogel 	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
938d8602bb9SJack F Vogel 		status = IXGBE_ERR_LINK_SETUP;
939d8602bb9SJack F Vogel 		goto out;
940d8602bb9SJack F Vogel 	}
941d8602bb9SJack F Vogel 
942770e416bSJack F Vogel 	/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
943770e416bSJack F Vogel 	if (hw->mac.orig_link_settings_stored)
944758cc3dcSJack F Vogel 		orig_autoc = hw->mac.orig_autoc;
945770e416bSJack F Vogel 	else
946770e416bSJack F Vogel 		orig_autoc = autoc;
947758cc3dcSJack F Vogel 
9480ecc2ff0SJack F Vogel 	link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
9490ecc2ff0SJack F Vogel 	pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
950770e416bSJack F Vogel 
951d8602bb9SJack F Vogel 	if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
952770e416bSJack F Vogel 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
953770e416bSJack F Vogel 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
954770e416bSJack F Vogel 		/* Set KX4/KX/KR support according to speed requested */
955770e416bSJack F Vogel 		autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP);
9563aa5b33aSKevin Lo 		if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
957770e416bSJack F Vogel 			if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)
958770e416bSJack F Vogel 				autoc |= IXGBE_AUTOC_KX4_SUPP;
9592969bf0eSJack F Vogel 			if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) &&
96079b36ec9SKevin Bowling 			    (hw->phy.smart_speed_active == false))
961770e416bSJack F Vogel 				autoc |= IXGBE_AUTOC_KR_SUPP;
9623aa5b33aSKevin Lo 		}
963770e416bSJack F Vogel 		if (speed & IXGBE_LINK_SPEED_1GB_FULL)
964770e416bSJack F Vogel 			autoc |= IXGBE_AUTOC_KX_SUPP;
965770e416bSJack F Vogel 	} else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) &&
966770e416bSJack F Vogel 		   (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN ||
967770e416bSJack F Vogel 		    link_mode == IXGBE_AUTOC_LMS_1G_AN)) {
968770e416bSJack F Vogel 		/* Switch from 1G SFI to 10G SFI if requested */
969770e416bSJack F Vogel 		if ((speed == IXGBE_LINK_SPEED_10GB_FULL) &&
970770e416bSJack F Vogel 		    (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) {
971770e416bSJack F Vogel 			autoc &= ~IXGBE_AUTOC_LMS_MASK;
972770e416bSJack F Vogel 			autoc |= IXGBE_AUTOC_LMS_10G_SERIAL;
973770e416bSJack F Vogel 		}
974770e416bSJack F Vogel 	} else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) &&
975770e416bSJack F Vogel 		   (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) {
976770e416bSJack F Vogel 		/* Switch from 10G SFI to 1G SFI if requested */
977770e416bSJack F Vogel 		if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
978770e416bSJack F Vogel 		    (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) {
979770e416bSJack F Vogel 			autoc &= ~IXGBE_AUTOC_LMS_MASK;
980758cc3dcSJack F Vogel 			if (autoneg || hw->phy.type == ixgbe_phy_qsfp_intel)
981770e416bSJack F Vogel 				autoc |= IXGBE_AUTOC_LMS_1G_AN;
982770e416bSJack F Vogel 			else
983770e416bSJack F Vogel 				autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
984770e416bSJack F Vogel 		}
985770e416bSJack F Vogel 	}
986770e416bSJack F Vogel 
987758cc3dcSJack F Vogel 	if (autoc != current_autoc) {
988770e416bSJack F Vogel 		/* Restart link */
98979b36ec9SKevin Bowling 		status = hw->mac.ops.prot_autoc_write(hw, autoc, false);
990758cc3dcSJack F Vogel 		if (status != IXGBE_SUCCESS)
991758cc3dcSJack F Vogel 			goto out;
992770e416bSJack F Vogel 
993770e416bSJack F Vogel 		/* Only poll for autoneg to complete if specified to do so */
994770e416bSJack F Vogel 		if (autoneg_wait_to_complete) {
995770e416bSJack F Vogel 			if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
996770e416bSJack F Vogel 			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
997770e416bSJack F Vogel 			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
998770e416bSJack F Vogel 				links_reg = 0; /*Just in case Autoneg time=0*/
999770e416bSJack F Vogel 				for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
1000770e416bSJack F Vogel 					links_reg =
1001770e416bSJack F Vogel 					       IXGBE_READ_REG(hw, IXGBE_LINKS);
1002770e416bSJack F Vogel 					if (links_reg & IXGBE_LINKS_KX_AN_COMP)
1003770e416bSJack F Vogel 						break;
1004770e416bSJack F Vogel 					msec_delay(100);
1005770e416bSJack F Vogel 				}
1006770e416bSJack F Vogel 				if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
1007770e416bSJack F Vogel 					status =
1008770e416bSJack F Vogel 						IXGBE_ERR_AUTONEG_NOT_COMPLETE;
1009770e416bSJack F Vogel 					DEBUGOUT("Autoneg did not complete.\n");
1010770e416bSJack F Vogel 				}
1011770e416bSJack F Vogel 			}
1012770e416bSJack F Vogel 		}
1013770e416bSJack F Vogel 
1014770e416bSJack F Vogel 		/* Add delay to filter out noises during initial link setup */
1015770e416bSJack F Vogel 		msec_delay(50);
1016770e416bSJack F Vogel 	}
1017770e416bSJack F Vogel 
1018770e416bSJack F Vogel out:
1019770e416bSJack F Vogel 	return status;
1020770e416bSJack F Vogel }
1021770e416bSJack F Vogel 
1022770e416bSJack F Vogel /**
10232969bf0eSJack F Vogel  * ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field
1024770e416bSJack F Vogel  * @hw: pointer to hardware structure
1025770e416bSJack F Vogel  * @speed: new link speed
102679b36ec9SKevin Bowling  * @autoneg_wait_to_complete: true if waiting is needed to complete
1027770e416bSJack F Vogel  *
1028770e416bSJack F Vogel  * Restarts link on PHY and MAC based on settings passed in.
1029770e416bSJack F Vogel  **/
ixgbe_setup_copper_link_82599(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)10302969bf0eSJack F Vogel static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
1031770e416bSJack F Vogel 					 ixgbe_link_speed speed,
1032770e416bSJack F Vogel 					 bool autoneg_wait_to_complete)
1033770e416bSJack F Vogel {
1034770e416bSJack F Vogel 	s32 status;
1035770e416bSJack F Vogel 
10362969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_setup_copper_link_82599");
10372969bf0eSJack F Vogel 
1038770e416bSJack F Vogel 	/* Setup the PHY according to input speed */
10390ecc2ff0SJack F Vogel 	status = hw->phy.ops.setup_link_speed(hw, speed,
1040770e416bSJack F Vogel 					      autoneg_wait_to_complete);
1041770e416bSJack F Vogel 	/* Set up MAC */
10422969bf0eSJack F Vogel 	ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete);
1043770e416bSJack F Vogel 
1044770e416bSJack F Vogel 	return status;
1045770e416bSJack F Vogel }
10461a4e3449SJack F Vogel 
1047770e416bSJack F Vogel /**
1048770e416bSJack F Vogel  * ixgbe_reset_hw_82599 - Perform hardware reset
1049770e416bSJack F Vogel  * @hw: pointer to hardware structure
1050770e416bSJack F Vogel  *
1051770e416bSJack F Vogel  * Resets the hardware by resetting the transmit and receive units, masks
1052770e416bSJack F Vogel  * and clears all interrupts, perform a PHY reset, and perform a link (MAC)
1053770e416bSJack F Vogel  * reset.
1054770e416bSJack F Vogel  **/
ixgbe_reset_hw_82599(struct ixgbe_hw * hw)1055770e416bSJack F Vogel s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
1056770e416bSJack F Vogel {
105785d0a26eSJack F Vogel 	ixgbe_link_speed link_speed;
105885d0a26eSJack F Vogel 	s32 status;
1059758cc3dcSJack F Vogel 	u32 ctrl = 0;
1060758cc3dcSJack F Vogel 	u32 i, autoc, autoc2;
1061fd75b91dSJack F Vogel 	u32 curr_lms;
106279b36ec9SKevin Bowling 	bool link_up = false;
1063770e416bSJack F Vogel 
10642969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_reset_hw_82599");
10652969bf0eSJack F Vogel 
1066770e416bSJack F Vogel 	/* Call adapter stop to disable tx/rx and clear interrupts */
106785d0a26eSJack F Vogel 	status = hw->mac.ops.stop_adapter(hw);
106885d0a26eSJack F Vogel 	if (status != IXGBE_SUCCESS)
106985d0a26eSJack F Vogel 		goto reset_hw_out;
107085d0a26eSJack F Vogel 
107185d0a26eSJack F Vogel 	/* flush pending Tx transactions */
107285d0a26eSJack F Vogel 	ixgbe_clear_tx_pending(hw);
1073770e416bSJack F Vogel 
1074770e416bSJack F Vogel 	/* PHY ops must be identified and initialized prior to reset */
1075770e416bSJack F Vogel 
1076770e416bSJack F Vogel 	/* Identify PHY and related function pointers */
1077770e416bSJack F Vogel 	status = hw->phy.ops.init(hw);
1078770e416bSJack F Vogel 
1079770e416bSJack F Vogel 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
1080770e416bSJack F Vogel 		goto reset_hw_out;
1081770e416bSJack F Vogel 
1082770e416bSJack F Vogel 	/* Setup SFP module if there is one present. */
1083770e416bSJack F Vogel 	if (hw->phy.sfp_setup_needed) {
1084770e416bSJack F Vogel 		status = hw->mac.ops.setup_sfp(hw);
108579b36ec9SKevin Bowling 		hw->phy.sfp_setup_needed = false;
1086770e416bSJack F Vogel 	}
1087770e416bSJack F Vogel 
1088770e416bSJack F Vogel 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
1089770e416bSJack F Vogel 		goto reset_hw_out;
1090770e416bSJack F Vogel 
1091770e416bSJack F Vogel 	/* Reset PHY */
109279b36ec9SKevin Bowling 	if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
1093770e416bSJack F Vogel 		hw->phy.ops.reset(hw);
1094770e416bSJack F Vogel 
1095fd75b91dSJack F Vogel 	/* remember AUTOC from before we reset */
1096758cc3dcSJack F Vogel 	curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
1097fd75b91dSJack F Vogel 
1098c0014855SJack F Vogel mac_reset_top:
1099770e416bSJack F Vogel 	/*
110085d0a26eSJack F Vogel 	 * Issue global reset to the MAC.  Needs to be SW reset if link is up.
110185d0a26eSJack F Vogel 	 * If link reset is used when link is up, it might reset the PHY when
110285d0a26eSJack F Vogel 	 * mng is using it.  If link is down or the flag to force full link
110385d0a26eSJack F Vogel 	 * reset is set, then perform link reset.
1104770e416bSJack F Vogel 	 */
110585d0a26eSJack F Vogel 	ctrl = IXGBE_CTRL_LNK_RST;
110685d0a26eSJack F Vogel 	if (!hw->force_full_reset) {
110779b36ec9SKevin Bowling 		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
110885d0a26eSJack F Vogel 		if (link_up)
110985d0a26eSJack F Vogel 			ctrl = IXGBE_CTRL_RST;
111085d0a26eSJack F Vogel 	}
111185d0a26eSJack F Vogel 
111285d0a26eSJack F Vogel 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
111385d0a26eSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
1114770e416bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
1115770e416bSJack F Vogel 
1116758cc3dcSJack F Vogel 	/* Poll for reset bit to self-clear meaning reset is complete */
1117770e416bSJack F Vogel 	for (i = 0; i < 10; i++) {
1118770e416bSJack F Vogel 		usec_delay(1);
1119770e416bSJack F Vogel 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
112085d0a26eSJack F Vogel 		if (!(ctrl & IXGBE_CTRL_RST_MASK))
1121770e416bSJack F Vogel 			break;
1122770e416bSJack F Vogel 	}
112385d0a26eSJack F Vogel 
112485d0a26eSJack F Vogel 	if (ctrl & IXGBE_CTRL_RST_MASK) {
1125770e416bSJack F Vogel 		status = IXGBE_ERR_RESET_FAILED;
1126770e416bSJack F Vogel 		DEBUGOUT("Reset polling failed to complete.\n");
1127770e416bSJack F Vogel 	}
1128c0014855SJack F Vogel 
112985d0a26eSJack F Vogel 	msec_delay(50);
113085d0a26eSJack F Vogel 
1131c0014855SJack F Vogel 	/*
1132c0014855SJack F Vogel 	 * Double resets are required for recovery from certain error
1133758cc3dcSJack F Vogel 	 * conditions.  Between resets, it is necessary to stall to
1134758cc3dcSJack F Vogel 	 * allow time for any pending HW events to complete.
1135c0014855SJack F Vogel 	 */
1136c0014855SJack F Vogel 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
1137c0014855SJack F Vogel 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
1138c0014855SJack F Vogel 		goto mac_reset_top;
1139c0014855SJack F Vogel 	}
1140770e416bSJack F Vogel 
1141770e416bSJack F Vogel 	/*
1142770e416bSJack F Vogel 	 * Store the original AUTOC/AUTOC2 values if they have not been
1143770e416bSJack F Vogel 	 * stored off yet.  Otherwise restore the stored original
1144770e416bSJack F Vogel 	 * values since the reset operation sets back to defaults.
1145770e416bSJack F Vogel 	 */
1146758cc3dcSJack F Vogel 	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
1147770e416bSJack F Vogel 	autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
11480ecc2ff0SJack F Vogel 
11490ecc2ff0SJack F Vogel 	/* Enable link if disabled in NVM */
11500ecc2ff0SJack F Vogel 	if (autoc2 & IXGBE_AUTOC2_LINK_DISABLE_MASK) {
11510ecc2ff0SJack F Vogel 		autoc2 &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK;
11520ecc2ff0SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
11530ecc2ff0SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
11540ecc2ff0SJack F Vogel 	}
11550ecc2ff0SJack F Vogel 
115679b36ec9SKevin Bowling 	if (hw->mac.orig_link_settings_stored == false) {
1157758cc3dcSJack F Vogel 		hw->mac.orig_autoc = autoc;
1158770e416bSJack F Vogel 		hw->mac.orig_autoc2 = autoc2;
115979b36ec9SKevin Bowling 		hw->mac.orig_link_settings_stored = true;
1160770e416bSJack F Vogel 	} else {
1161fd75b91dSJack F Vogel 
1162fd75b91dSJack F Vogel 		/* If MNG FW is running on a multi-speed device that
1163fd75b91dSJack F Vogel 		 * doesn't autoneg with out driver support we need to
1164fd75b91dSJack F Vogel 		 * leave LMS in the state it was before we MAC reset.
1165fd75b91dSJack F Vogel 		 * Likewise if we support WoL we don't want change the
1166fd75b91dSJack F Vogel 		 * LMS state.
1167fd75b91dSJack F Vogel 		 */
1168758cc3dcSJack F Vogel 		if ((hw->phy.multispeed_fiber && ixgbe_mng_enabled(hw)) ||
1169fd75b91dSJack F Vogel 		    hw->wol_enabled)
1170fd75b91dSJack F Vogel 			hw->mac.orig_autoc =
1171fd75b91dSJack F Vogel 				(hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
1172fd75b91dSJack F Vogel 				curr_lms;
1173fd75b91dSJack F Vogel 
1174758cc3dcSJack F Vogel 		if (autoc != hw->mac.orig_autoc) {
1175758cc3dcSJack F Vogel 			status = hw->mac.ops.prot_autoc_write(hw,
1176758cc3dcSJack F Vogel 							hw->mac.orig_autoc,
117779b36ec9SKevin Bowling 							false);
1178758cc3dcSJack F Vogel 			if (status != IXGBE_SUCCESS)
11790ecc2ff0SJack F Vogel 				goto reset_hw_out;
11800ecc2ff0SJack F Vogel 		}
11810ecc2ff0SJack F Vogel 
1182770e416bSJack F Vogel 		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
1183770e416bSJack F Vogel 		    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
1184770e416bSJack F Vogel 			autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
1185770e416bSJack F Vogel 			autoc2 |= (hw->mac.orig_autoc2 &
1186770e416bSJack F Vogel 				   IXGBE_AUTOC2_UPPER_MASK);
1187770e416bSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
1188770e416bSJack F Vogel 		}
1189770e416bSJack F Vogel 	}
1190770e416bSJack F Vogel 
1191d8602bb9SJack F Vogel 	/* Store the permanent mac address */
1192d8602bb9SJack F Vogel 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
1193d8602bb9SJack F Vogel 
1194770e416bSJack F Vogel 	/*
1195770e416bSJack F Vogel 	 * Store MAC address from RAR0, clear receive address registers, and
1196770e416bSJack F Vogel 	 * clear the multicast table.  Also reset num_rar_entries to 128,
1197770e416bSJack F Vogel 	 * since we modify this value when programming the SAN MAC address.
1198770e416bSJack F Vogel 	 */
1199770e416bSJack F Vogel 	hw->mac.num_rar_entries = 128;
1200770e416bSJack F Vogel 	hw->mac.ops.init_rx_addrs(hw);
1201770e416bSJack F Vogel 
1202770e416bSJack F Vogel 	/* Store the permanent SAN mac address */
1203770e416bSJack F Vogel 	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
1204770e416bSJack F Vogel 
1205770e416bSJack F Vogel 	/* Add the SAN MAC address to the RAR only if it's a valid address */
1206770e416bSJack F Vogel 	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
1207a621e3c8SJack F Vogel 		/* Save the SAN MAC RAR index */
1208a621e3c8SJack F Vogel 		hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
1209a621e3c8SJack F Vogel 
12108eb6488eSEric Joyner 		hw->mac.ops.set_rar(hw, hw->mac.san_mac_rar_index,
12118eb6488eSEric Joyner 				    hw->mac.san_addr, 0, IXGBE_RAH_AV);
12128eb6488eSEric Joyner 
12138eb6488eSEric Joyner 		/* clear VMDq pool/queue selection for this RAR */
12148eb6488eSEric Joyner 		hw->mac.ops.clear_vmdq(hw, hw->mac.san_mac_rar_index,
12158eb6488eSEric Joyner 				       IXGBE_CLEAR_VMDQ_ALL);
12168eb6488eSEric Joyner 
1217770e416bSJack F Vogel 		/* Reserve the last RAR for the SAN MAC address */
1218770e416bSJack F Vogel 		hw->mac.num_rar_entries--;
1219770e416bSJack F Vogel 	}
1220770e416bSJack F Vogel 
12212969bf0eSJack F Vogel 	/* Store the alternative WWNN/WWPN prefix */
12222969bf0eSJack F Vogel 	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
12232969bf0eSJack F Vogel 				   &hw->mac.wwpn_prefix);
12242969bf0eSJack F Vogel 
1225770e416bSJack F Vogel reset_hw_out:
1226770e416bSJack F Vogel 	return status;
1227770e416bSJack F Vogel }
1228770e416bSJack F Vogel 
1229770e416bSJack F Vogel /**
1230758cc3dcSJack F Vogel  * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete
1231758cc3dcSJack F Vogel  * @hw: pointer to hardware structure
1232758cc3dcSJack F Vogel  * @fdircmd: current value of FDIRCMD register
1233758cc3dcSJack F Vogel  */
ixgbe_fdir_check_cmd_complete(struct ixgbe_hw * hw,u32 * fdircmd)1234758cc3dcSJack F Vogel static s32 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, u32 *fdircmd)
1235758cc3dcSJack F Vogel {
1236758cc3dcSJack F Vogel 	int i;
1237758cc3dcSJack F Vogel 
1238758cc3dcSJack F Vogel 	for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
1239758cc3dcSJack F Vogel 		*fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
1240758cc3dcSJack F Vogel 		if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK))
1241758cc3dcSJack F Vogel 			return IXGBE_SUCCESS;
1242758cc3dcSJack F Vogel 		usec_delay(10);
1243758cc3dcSJack F Vogel 	}
1244758cc3dcSJack F Vogel 
1245758cc3dcSJack F Vogel 	return IXGBE_ERR_FDIR_CMD_INCOMPLETE;
1246758cc3dcSJack F Vogel }
1247758cc3dcSJack F Vogel 
1248758cc3dcSJack F Vogel /**
1249770e416bSJack F Vogel  * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
1250770e416bSJack F Vogel  * @hw: pointer to hardware structure
1251770e416bSJack F Vogel  **/
ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw * hw)1252770e416bSJack F Vogel s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
1253770e416bSJack F Vogel {
1254758cc3dcSJack F Vogel 	s32 err;
1255d8602bb9SJack F Vogel 	int i;
1256770e416bSJack F Vogel 	u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
1257758cc3dcSJack F Vogel 	u32 fdircmd;
1258770e416bSJack F Vogel 	fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
1259d8602bb9SJack F Vogel 
12602969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_reinit_fdir_tables_82599");
12612969bf0eSJack F Vogel 
1262d8602bb9SJack F Vogel 	/*
1263d8602bb9SJack F Vogel 	 * Before starting reinitialization process,
1264d8602bb9SJack F Vogel 	 * FDIRCMD.CMD must be zero.
1265d8602bb9SJack F Vogel 	 */
1266758cc3dcSJack F Vogel 	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
1267758cc3dcSJack F Vogel 	if (err) {
1268758cc3dcSJack F Vogel 		DEBUGOUT("Flow Director previous command did not complete, aborting table re-initialization.\n");
1269758cc3dcSJack F Vogel 		return err;
1270d8602bb9SJack F Vogel 	}
1271d8602bb9SJack F Vogel 
1272770e416bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
1273770e416bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
1274d8602bb9SJack F Vogel 	/*
1275d8602bb9SJack F Vogel 	 * 82599 adapters flow director init flow cannot be restarted,
1276d8602bb9SJack F Vogel 	 * Workaround 82599 silicon errata by performing the following steps
1277d8602bb9SJack F Vogel 	 * before re-writing the FDIRCTRL control register with the same value.
1278d8602bb9SJack F Vogel 	 * - write 1 to bit 8 of FDIRCMD register &
1279d8602bb9SJack F Vogel 	 * - write 0 to bit 8 of FDIRCMD register
1280d8602bb9SJack F Vogel 	 */
1281d8602bb9SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
1282d8602bb9SJack F Vogel 			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
1283d8602bb9SJack F Vogel 			 IXGBE_FDIRCMD_CLEARHT));
1284d8602bb9SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
1285d8602bb9SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
1286d8602bb9SJack F Vogel 			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
1287d8602bb9SJack F Vogel 			 ~IXGBE_FDIRCMD_CLEARHT));
1288d8602bb9SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
1289d8602bb9SJack F Vogel 	/*
1290d8602bb9SJack F Vogel 	 * Clear FDIR Hash register to clear any leftover hashes
1291d8602bb9SJack F Vogel 	 * waiting to be programmed.
1292d8602bb9SJack F Vogel 	 */
1293d8602bb9SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00);
1294d8602bb9SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
1295d8602bb9SJack F Vogel 
1296770e416bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
1297d8602bb9SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
1298d8602bb9SJack F Vogel 
1299d8602bb9SJack F Vogel 	/* Poll init-done after we write FDIRCTRL register */
1300d8602bb9SJack F Vogel 	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
1301d8602bb9SJack F Vogel 		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
1302d8602bb9SJack F Vogel 				   IXGBE_FDIRCTRL_INIT_DONE)
1303d8602bb9SJack F Vogel 			break;
13040ecc2ff0SJack F Vogel 		msec_delay(1);
1305d8602bb9SJack F Vogel 	}
1306d8602bb9SJack F Vogel 	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
1307d8602bb9SJack F Vogel 		DEBUGOUT("Flow Director Signature poll time exceeded!\n");
1308d8602bb9SJack F Vogel 		return IXGBE_ERR_FDIR_REINIT_FAILED;
1309d8602bb9SJack F Vogel 	}
1310d8602bb9SJack F Vogel 
1311d8602bb9SJack F Vogel 	/* Clear FDIR statistics registers (read to clear) */
1312d8602bb9SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT);
1313d8602bb9SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT);
1314d8602bb9SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
1315d8602bb9SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
1316d8602bb9SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_FDIRLEN);
1317770e416bSJack F Vogel 
1318770e416bSJack F Vogel 	return IXGBE_SUCCESS;
1319770e416bSJack F Vogel }
1320770e416bSJack F Vogel 
1321770e416bSJack F Vogel /**
132285d0a26eSJack F Vogel  * ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
1323770e416bSJack F Vogel  * @hw: pointer to hardware structure
132485d0a26eSJack F Vogel  * @fdirctrl: value to write to flow director control register
1325770e416bSJack F Vogel  **/
ixgbe_fdir_enable_82599(struct ixgbe_hw * hw,u32 fdirctrl)132685d0a26eSJack F Vogel static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
1327770e416bSJack F Vogel {
1328770e416bSJack F Vogel 	int i;
1329770e416bSJack F Vogel 
133085d0a26eSJack F Vogel 	DEBUGFUNC("ixgbe_fdir_enable_82599");
1331770e416bSJack F Vogel 
1332770e416bSJack F Vogel 	/* Prime the keys for hashing */
13331a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
13341a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
1335770e416bSJack F Vogel 
1336770e416bSJack F Vogel 	/*
1337770e416bSJack F Vogel 	 * Poll init-done after we write the register.  Estimated times:
1338770e416bSJack F Vogel 	 *      10G: PBALLOC = 11b, timing is 60us
1339770e416bSJack F Vogel 	 *       1G: PBALLOC = 11b, timing is 600us
1340770e416bSJack F Vogel 	 *     100M: PBALLOC = 11b, timing is 6ms
1341770e416bSJack F Vogel 	 *
1342770e416bSJack F Vogel 	 *     Multiple these timings by 4 if under full Rx load
1343770e416bSJack F Vogel 	 *
1344770e416bSJack F Vogel 	 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
1345770e416bSJack F Vogel 	 * 1 msec per poll time.  If we're at line rate and drop to 100M, then
1346770e416bSJack F Vogel 	 * this might not finish in our poll time, but we can live with that
1347770e416bSJack F Vogel 	 * for now.
1348770e416bSJack F Vogel 	 */
1349770e416bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
1350770e416bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
1351770e416bSJack F Vogel 	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
1352770e416bSJack F Vogel 		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
1353770e416bSJack F Vogel 				   IXGBE_FDIRCTRL_INIT_DONE)
1354770e416bSJack F Vogel 			break;
1355770e416bSJack F Vogel 		msec_delay(1);
1356770e416bSJack F Vogel 	}
135785d0a26eSJack F Vogel 
1358770e416bSJack F Vogel 	if (i >= IXGBE_FDIR_INIT_DONE_POLL)
135985d0a26eSJack F Vogel 		DEBUGOUT("Flow Director poll time exceeded!\n");
136085d0a26eSJack F Vogel }
136185d0a26eSJack F Vogel 
136285d0a26eSJack F Vogel /**
136385d0a26eSJack F Vogel  * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
136485d0a26eSJack F Vogel  * @hw: pointer to hardware structure
136585d0a26eSJack F Vogel  * @fdirctrl: value to write to flow director control register, initially
136685d0a26eSJack F Vogel  *	     contains just the value of the Rx packet buffer allocation
136785d0a26eSJack F Vogel  **/
ixgbe_init_fdir_signature_82599(struct ixgbe_hw * hw,u32 fdirctrl)136885d0a26eSJack F Vogel s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
136985d0a26eSJack F Vogel {
137085d0a26eSJack F Vogel 	DEBUGFUNC("ixgbe_init_fdir_signature_82599");
137185d0a26eSJack F Vogel 
137285d0a26eSJack F Vogel 	/*
137385d0a26eSJack F Vogel 	 * Continue setup of fdirctrl register bits:
137485d0a26eSJack F Vogel 	 *  Move the flexible bytes to use the ethertype - shift 6 words
137585d0a26eSJack F Vogel 	 *  Set the maximum length per hash bucket to 0xA filters
137685d0a26eSJack F Vogel 	 *  Send interrupt when 64 filters are left
137785d0a26eSJack F Vogel 	 */
137885d0a26eSJack F Vogel 	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
137985d0a26eSJack F Vogel 		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
138085d0a26eSJack F Vogel 		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
138185d0a26eSJack F Vogel 
138285d0a26eSJack F Vogel 	/* write hashes and fdirctrl register, poll for completion */
138385d0a26eSJack F Vogel 	ixgbe_fdir_enable_82599(hw, fdirctrl);
1384770e416bSJack F Vogel 
1385770e416bSJack F Vogel 	return IXGBE_SUCCESS;
1386770e416bSJack F Vogel }
1387770e416bSJack F Vogel 
1388770e416bSJack F Vogel /**
1389770e416bSJack F Vogel  * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
1390770e416bSJack F Vogel  * @hw: pointer to hardware structure
139185d0a26eSJack F Vogel  * @fdirctrl: value to write to flow director control register, initially
139285d0a26eSJack F Vogel  *	     contains just the value of the Rx packet buffer allocation
139379b36ec9SKevin Bowling  * @cloud_mode: true - cloud mode, false - other mode
1394770e416bSJack F Vogel  **/
ixgbe_init_fdir_perfect_82599(struct ixgbe_hw * hw,u32 fdirctrl,bool cloud_mode)1395758cc3dcSJack F Vogel s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
1396758cc3dcSJack F Vogel 			bool cloud_mode)
1397770e416bSJack F Vogel {
13987d48aa4cSEric Joyner 	UNREFERENCED_1PARAMETER(cloud_mode);
13992969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_fdir_perfect_82599");
14002969bf0eSJack F Vogel 
1401770e416bSJack F Vogel 	/*
140285d0a26eSJack F Vogel 	 * Continue setup of fdirctrl register bits:
140385d0a26eSJack F Vogel 	 *  Turn perfect match filtering on
140485d0a26eSJack F Vogel 	 *  Report hash in RSS field of Rx wb descriptor
1405a9ca1c79SSean Bruno 	 *  Initialize the drop queue to queue 127
140685d0a26eSJack F Vogel 	 *  Move the flexible bytes to use the ethertype - shift 6 words
140785d0a26eSJack F Vogel 	 *  Set the maximum length per hash bucket to 0xA filters
140885d0a26eSJack F Vogel 	 *  Send interrupt when 64 (0x4 * 16) filters are left
1409770e416bSJack F Vogel 	 */
141085d0a26eSJack F Vogel 	fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH |
141185d0a26eSJack F Vogel 		    IXGBE_FDIRCTRL_REPORT_STATUS |
141285d0a26eSJack F Vogel 		    (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) |
141385d0a26eSJack F Vogel 		    (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
141485d0a26eSJack F Vogel 		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
141585d0a26eSJack F Vogel 		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
1416770e416bSJack F Vogel 
1417758cc3dcSJack F Vogel 	if (cloud_mode)
1418758cc3dcSJack F Vogel 		fdirctrl |=(IXGBE_FDIRCTRL_FILTERMODE_CLOUD <<
1419758cc3dcSJack F Vogel 					IXGBE_FDIRCTRL_FILTERMODE_SHIFT);
1420758cc3dcSJack F Vogel 
142185d0a26eSJack F Vogel 	/* write hashes and fdirctrl register, poll for completion */
142285d0a26eSJack F Vogel 	ixgbe_fdir_enable_82599(hw, fdirctrl);
1423770e416bSJack F Vogel 
1424770e416bSJack F Vogel 	return IXGBE_SUCCESS;
1425770e416bSJack F Vogel }
1426770e416bSJack F Vogel 
1427a9ca1c79SSean Bruno /**
1428a9ca1c79SSean Bruno  * ixgbe_set_fdir_drop_queue_82599 - Set Flow Director drop queue
1429a9ca1c79SSean Bruno  * @hw: pointer to hardware structure
1430a9ca1c79SSean Bruno  * @dropqueue: Rx queue index used for the dropped packets
1431a9ca1c79SSean Bruno  **/
ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw * hw,u8 dropqueue)1432a9ca1c79SSean Bruno void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue)
1433a9ca1c79SSean Bruno {
1434a9ca1c79SSean Bruno 	u32 fdirctrl;
1435a9ca1c79SSean Bruno 
1436a9ca1c79SSean Bruno 	DEBUGFUNC("ixgbe_set_fdir_drop_queue_82599");
1437a9ca1c79SSean Bruno 	/* Clear init done bit and drop queue field */
1438a9ca1c79SSean Bruno 	fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
1439a9ca1c79SSean Bruno 	fdirctrl &= ~(IXGBE_FDIRCTRL_DROP_Q_MASK | IXGBE_FDIRCTRL_INIT_DONE);
1440a9ca1c79SSean Bruno 
1441a9ca1c79SSean Bruno 	/* Set drop queue */
1442a9ca1c79SSean Bruno 	fdirctrl |= (dropqueue << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
1443a9ca1c79SSean Bruno 	if ((hw->mac.type == ixgbe_mac_X550) ||
14448eb6488eSEric Joyner 	    (hw->mac.type == ixgbe_mac_X550EM_x) ||
14458eb6488eSEric Joyner 	    (hw->mac.type == ixgbe_mac_X550EM_a))
1446a9ca1c79SSean Bruno 		fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH;
1447a9ca1c79SSean Bruno 
1448a9ca1c79SSean Bruno 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
1449a9ca1c79SSean Bruno 			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
1450a9ca1c79SSean Bruno 			 IXGBE_FDIRCMD_CLEARHT));
1451a9ca1c79SSean Bruno 	IXGBE_WRITE_FLUSH(hw);
1452a9ca1c79SSean Bruno 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
1453a9ca1c79SSean Bruno 			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
1454a9ca1c79SSean Bruno 			 ~IXGBE_FDIRCMD_CLEARHT));
1455a9ca1c79SSean Bruno 	IXGBE_WRITE_FLUSH(hw);
1456a9ca1c79SSean Bruno 
1457a9ca1c79SSean Bruno 	/* write hashes and fdirctrl register, poll for completion */
1458a9ca1c79SSean Bruno 	ixgbe_fdir_enable_82599(hw, fdirctrl);
1459a9ca1c79SSean Bruno }
1460a9ca1c79SSean Bruno 
14611a4e3449SJack F Vogel /*
14621a4e3449SJack F Vogel  * These defines allow us to quickly generate all of the necessary instructions
14631a4e3449SJack F Vogel  * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
14641a4e3449SJack F Vogel  * for values 0 through 15
14651a4e3449SJack F Vogel  */
14661a4e3449SJack F Vogel #define IXGBE_ATR_COMMON_HASH_KEY \
14671a4e3449SJack F Vogel 		(IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY)
14681a4e3449SJack F Vogel #define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \
14691a4e3449SJack F Vogel do { \
14701a4e3449SJack F Vogel 	u32 n = (_n); \
1471182b3808SJack F Vogel 	if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \
14721a4e3449SJack F Vogel 		common_hash ^= lo_hash_dword >> n; \
1473182b3808SJack F Vogel 	else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
14741a4e3449SJack F Vogel 		bucket_hash ^= lo_hash_dword >> n; \
1475182b3808SJack F Vogel 	else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \
1476182b3808SJack F Vogel 		sig_hash ^= lo_hash_dword << (16 - n); \
1477182b3808SJack F Vogel 	if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \
14781a4e3449SJack F Vogel 		common_hash ^= hi_hash_dword >> n; \
1479182b3808SJack F Vogel 	else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
14801a4e3449SJack F Vogel 		bucket_hash ^= hi_hash_dword >> n; \
1481182b3808SJack F Vogel 	else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \
1482182b3808SJack F Vogel 		sig_hash ^= hi_hash_dword << (16 - n); \
1483758cc3dcSJack F Vogel } while (0)
14841a4e3449SJack F Vogel 
14851a4e3449SJack F Vogel /**
14861a4e3449SJack F Vogel  * ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash
14877d48aa4cSEric Joyner  * @input: input bitstream to compute the hash on
14887d48aa4cSEric Joyner  * @common: compressed common input dword
14891a4e3449SJack F Vogel  *
14901a4e3449SJack F Vogel  * This function is almost identical to the function above but contains
1491758cc3dcSJack F Vogel  * several optimizations such as unwinding all of the loops, letting the
14921a4e3449SJack F Vogel  * compiler work out all of the conditional ifs since the keys are static
14931a4e3449SJack F Vogel  * defines, and computing two keys at once since the hashed dword stream
14941a4e3449SJack F Vogel  * will be the same for both keys.
14951a4e3449SJack F Vogel  **/
ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,union ixgbe_atr_hash_dword common)149685d0a26eSJack F Vogel u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
1497182b3808SJack F Vogel 				     union ixgbe_atr_hash_dword common)
14981a4e3449SJack F Vogel {
1499182b3808SJack F Vogel 	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
1500182b3808SJack F Vogel 	u32 sig_hash = 0, bucket_hash = 0, common_hash = 0;
15011a4e3449SJack F Vogel 
1502182b3808SJack F Vogel 	/* record the flow_vm_vlan bits as they are a key part to the hash */
1503182b3808SJack F Vogel 	flow_vm_vlan = IXGBE_NTOHL(input.dword);
15041a4e3449SJack F Vogel 
15051a4e3449SJack F Vogel 	/* generate common hash dword */
1506182b3808SJack F Vogel 	hi_hash_dword = IXGBE_NTOHL(common.dword);
15071a4e3449SJack F Vogel 
15081a4e3449SJack F Vogel 	/* low dword is word swapped version of common */
1509182b3808SJack F Vogel 	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
15101a4e3449SJack F Vogel 
1511182b3808SJack F Vogel 	/* apply flow ID/VM pool/VLAN ID bits to hash words */
1512182b3808SJack F Vogel 	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
1513182b3808SJack F Vogel 
1514182b3808SJack F Vogel 	/* Process bits 0 and 16 */
1515182b3808SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(0);
15161a4e3449SJack F Vogel 
15171a4e3449SJack F Vogel 	/*
1518182b3808SJack F Vogel 	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
1519182b3808SJack F Vogel 	 * delay this because bit 0 of the stream should not be processed
1520758cc3dcSJack F Vogel 	 * so we do not add the VLAN until after bit 0 was processed
15211a4e3449SJack F Vogel 	 */
1522182b3808SJack F Vogel 	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
1523182b3808SJack F Vogel 
1524182b3808SJack F Vogel 	/* Process remaining 30 bit of the key */
15251a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(1);
15261a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(2);
15271a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(3);
15281a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(4);
15291a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(5);
15301a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(6);
15311a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(7);
15321a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(8);
15331a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(9);
15341a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(10);
15351a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(11);
15361a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(12);
15371a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(13);
15381a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(14);
15391a4e3449SJack F Vogel 	IXGBE_COMPUTE_SIG_HASH_ITERATION(15);
15401a4e3449SJack F Vogel 
15411a4e3449SJack F Vogel 	/* combine common_hash result with signature and bucket hashes */
15421a4e3449SJack F Vogel 	bucket_hash ^= common_hash;
1543182b3808SJack F Vogel 	bucket_hash &= IXGBE_ATR_HASH_MASK;
1544182b3808SJack F Vogel 
1545182b3808SJack F Vogel 	sig_hash ^= common_hash << 16;
1546182b3808SJack F Vogel 	sig_hash &= IXGBE_ATR_HASH_MASK << 16;
15471a4e3449SJack F Vogel 
15481a4e3449SJack F Vogel 	/* return completed signature hash */
1549182b3808SJack F Vogel 	return sig_hash ^ bucket_hash;
1550770e416bSJack F Vogel }
1551770e416bSJack F Vogel 
1552770e416bSJack F Vogel /**
1553edef2769SRadoslaw Tyl  * ixgbe_fdir_add_signature_filter_82599 - Adds a signature hash filter
1554770e416bSJack F Vogel  * @hw: pointer to hardware structure
155585d0a26eSJack F Vogel  * @input: unique input dword
155685d0a26eSJack F Vogel  * @common: compressed common input dword
1557770e416bSJack F Vogel  * @queue: queue index to direct traffic to
1558758cc3dcSJack F Vogel  *
1559758cc3dcSJack F Vogel  * Note that the tunnel bit in input must not be set when the hardware
1560758cc3dcSJack F Vogel  * tunneling support does not exist.
1561770e416bSJack F Vogel  **/
ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw * hw,union ixgbe_atr_hash_dword input,union ixgbe_atr_hash_dword common,u8 queue)1562a9ca1c79SSean Bruno void ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
1563182b3808SJack F Vogel 					   union ixgbe_atr_hash_dword input,
1564182b3808SJack F Vogel 					   union ixgbe_atr_hash_dword common,
1565770e416bSJack F Vogel 					   u8 queue)
1566770e416bSJack F Vogel {
1567770e416bSJack F Vogel 	u64 fdirhashcmd;
1568758cc3dcSJack F Vogel 	u8 flow_type;
1569758cc3dcSJack F Vogel 	bool tunnel;
15701a4e3449SJack F Vogel 	u32 fdircmd;
1571770e416bSJack F Vogel 
15722969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
15732969bf0eSJack F Vogel 
15741a4e3449SJack F Vogel 	/*
15751a4e3449SJack F Vogel 	 * Get the flow_type in order to program FDIRCMD properly
15761a4e3449SJack F Vogel 	 * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
1577758cc3dcSJack F Vogel 	 * fifth is FDIRCMD.TUNNEL_FILTER
15781a4e3449SJack F Vogel 	 */
1579758cc3dcSJack F Vogel 	tunnel = !!(input.formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK);
1580758cc3dcSJack F Vogel 	flow_type = input.formatted.flow_type &
1581758cc3dcSJack F Vogel 		    (IXGBE_ATR_L4TYPE_TUNNEL_MASK - 1);
1582758cc3dcSJack F Vogel 	switch (flow_type) {
15831a4e3449SJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_TCPV4:
15841a4e3449SJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_UDPV4:
15851a4e3449SJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
15861a4e3449SJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_TCPV6:
15871a4e3449SJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_UDPV6:
15881a4e3449SJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_SCTPV6:
15891a4e3449SJack F Vogel 		break;
15901a4e3449SJack F Vogel 	default:
15911a4e3449SJack F Vogel 		DEBUGOUT(" Error on flow type input\n");
1592a9ca1c79SSean Bruno 		return;
15931a4e3449SJack F Vogel 	}
1594770e416bSJack F Vogel 
15951a4e3449SJack F Vogel 	/* configure FDIRCMD register */
15961a4e3449SJack F Vogel 	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
15971a4e3449SJack F Vogel 		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
1598758cc3dcSJack F Vogel 	fdircmd |= (u32)flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
1599182b3808SJack F Vogel 	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
1600758cc3dcSJack F Vogel 	if (tunnel)
1601758cc3dcSJack F Vogel 		fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER;
1602770e416bSJack F Vogel 
1603770e416bSJack F Vogel 	/*
1604770e416bSJack F Vogel 	 * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
1605770e416bSJack F Vogel 	 * is for FDIRCMD.  Then do a 64-bit register write from FDIRHASH.
1606770e416bSJack F Vogel 	 */
1607182b3808SJack F Vogel 	fdirhashcmd = (u64)fdircmd << 32;
1608994dd632SGuinan Sun 	fdirhashcmd |= (u64)ixgbe_atr_compute_sig_hash_82599(input, common);
1609770e416bSJack F Vogel 	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
1610770e416bSJack F Vogel 
16111a4e3449SJack F Vogel 	DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
16121a4e3449SJack F Vogel 
1613a9ca1c79SSean Bruno 	return;
1614770e416bSJack F Vogel }
1615770e416bSJack F Vogel 
161685d0a26eSJack F Vogel #define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
161785d0a26eSJack F Vogel do { \
161885d0a26eSJack F Vogel 	u32 n = (_n); \
161985d0a26eSJack F Vogel 	if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
162085d0a26eSJack F Vogel 		bucket_hash ^= lo_hash_dword >> n; \
162185d0a26eSJack F Vogel 	if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
162285d0a26eSJack F Vogel 		bucket_hash ^= hi_hash_dword >> n; \
1623758cc3dcSJack F Vogel } while (0)
162485d0a26eSJack F Vogel 
162585d0a26eSJack F Vogel /**
162685d0a26eSJack F Vogel  * ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash
16277d48aa4cSEric Joyner  * @input: input bitstream to compute the hash on
162885d0a26eSJack F Vogel  * @input_mask: mask for the input bitstream
162985d0a26eSJack F Vogel  *
1630758cc3dcSJack F Vogel  * This function serves two main purposes.  First it applies the input_mask
163185d0a26eSJack F Vogel  * to the atr_input resulting in a cleaned up atr_input data stream.
163285d0a26eSJack F Vogel  * Secondly it computes the hash and stores it in the bkt_hash field at
163385d0a26eSJack F Vogel  * the end of the input byte stream.  This way it will be available for
163485d0a26eSJack F Vogel  * future use without needing to recompute the hash.
163585d0a26eSJack F Vogel  **/
ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input * input,union ixgbe_atr_input * input_mask)163685d0a26eSJack F Vogel void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
163785d0a26eSJack F Vogel 					  union ixgbe_atr_input *input_mask)
163885d0a26eSJack F Vogel {
163985d0a26eSJack F Vogel 
164085d0a26eSJack F Vogel 	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
164185d0a26eSJack F Vogel 	u32 bucket_hash = 0;
1642758cc3dcSJack F Vogel 	u32 hi_dword = 0;
1643758cc3dcSJack F Vogel 	u32 i = 0;
164485d0a26eSJack F Vogel 
164585d0a26eSJack F Vogel 	/* Apply masks to input data */
1646758cc3dcSJack F Vogel 	for (i = 0; i < 14; i++)
1647758cc3dcSJack F Vogel 		input->dword_stream[i]  &= input_mask->dword_stream[i];
164885d0a26eSJack F Vogel 
164985d0a26eSJack F Vogel 	/* record the flow_vm_vlan bits as they are a key part to the hash */
165085d0a26eSJack F Vogel 	flow_vm_vlan = IXGBE_NTOHL(input->dword_stream[0]);
165185d0a26eSJack F Vogel 
165285d0a26eSJack F Vogel 	/* generate common hash dword */
1653758cc3dcSJack F Vogel 	for (i = 1; i <= 13; i++)
1654758cc3dcSJack F Vogel 		hi_dword ^= input->dword_stream[i];
1655758cc3dcSJack F Vogel 	hi_hash_dword = IXGBE_NTOHL(hi_dword);
165685d0a26eSJack F Vogel 
165785d0a26eSJack F Vogel 	/* low dword is word swapped version of common */
165885d0a26eSJack F Vogel 	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
165985d0a26eSJack F Vogel 
166085d0a26eSJack F Vogel 	/* apply flow ID/VM pool/VLAN ID bits to hash words */
166185d0a26eSJack F Vogel 	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
166285d0a26eSJack F Vogel 
166385d0a26eSJack F Vogel 	/* Process bits 0 and 16 */
166485d0a26eSJack F Vogel 	IXGBE_COMPUTE_BKT_HASH_ITERATION(0);
166585d0a26eSJack F Vogel 
166685d0a26eSJack F Vogel 	/*
166785d0a26eSJack F Vogel 	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
166885d0a26eSJack F Vogel 	 * delay this because bit 0 of the stream should not be processed
1669758cc3dcSJack F Vogel 	 * so we do not add the VLAN until after bit 0 was processed
167085d0a26eSJack F Vogel 	 */
167185d0a26eSJack F Vogel 	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
167285d0a26eSJack F Vogel 
167385d0a26eSJack F Vogel 	/* Process remaining 30 bit of the key */
1674758cc3dcSJack F Vogel 	for (i = 1; i <= 15; i++)
1675758cc3dcSJack F Vogel 		IXGBE_COMPUTE_BKT_HASH_ITERATION(i);
167685d0a26eSJack F Vogel 
167785d0a26eSJack F Vogel 	/*
167885d0a26eSJack F Vogel 	 * Limit hash to 13 bits since max bucket count is 8K.
167985d0a26eSJack F Vogel 	 * Store result at the end of the input stream.
168085d0a26eSJack F Vogel 	 */
168185d0a26eSJack F Vogel 	input->formatted.bkt_hash = bucket_hash & 0x1FFF;
168285d0a26eSJack F Vogel }
168385d0a26eSJack F Vogel 
1684770e416bSJack F Vogel /**
1685758cc3dcSJack F Vogel  * ixgbe_get_fdirtcpm_82599 - generate a TCP port from atr_input_masks
16861a4e3449SJack F Vogel  * @input_mask: mask to be bit swapped
16871a4e3449SJack F Vogel  *
16881a4e3449SJack F Vogel  * The source and destination port masks for flow director are bit swapped
16891a4e3449SJack F Vogel  * in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc.  In order to
16901a4e3449SJack F Vogel  * generate a correctly swapped value we need to bit swap the mask and that
16911a4e3449SJack F Vogel  * is what is accomplished by this function.
16921a4e3449SJack F Vogel  **/
ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input * input_mask)169385d0a26eSJack F Vogel static u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask)
16941a4e3449SJack F Vogel {
169585d0a26eSJack F Vogel 	u32 mask = IXGBE_NTOHS(input_mask->formatted.dst_port);
16961a4e3449SJack F Vogel 	mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
1697994dd632SGuinan Sun 	mask |= (u32)IXGBE_NTOHS(input_mask->formatted.src_port);
16981a4e3449SJack F Vogel 	mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
16991a4e3449SJack F Vogel 	mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
17001a4e3449SJack F Vogel 	mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
17011a4e3449SJack F Vogel 	return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8);
17021a4e3449SJack F Vogel }
17031a4e3449SJack F Vogel 
17041a4e3449SJack F Vogel /*
17051a4e3449SJack F Vogel  * These two macros are meant to address the fact that we have registers
17061a4e3449SJack F Vogel  * that are either all or in part big-endian.  As a result on big-endian
17071a4e3449SJack F Vogel  * systems we will end up byte swapping the value to little-endian before
17081a4e3449SJack F Vogel  * it is byte swapped again and written to the hardware in the original
17091a4e3449SJack F Vogel  * big-endian format.
17101a4e3449SJack F Vogel  */
17111a4e3449SJack F Vogel #define IXGBE_STORE_AS_BE32(_value) \
17121a4e3449SJack F Vogel 	(((u32)(_value) >> 24) | (((u32)(_value) & 0x00FF0000) >> 8) | \
17131a4e3449SJack F Vogel 	 (((u32)(_value) & 0x0000FF00) << 8) | ((u32)(_value) << 24))
17141a4e3449SJack F Vogel 
17151a4e3449SJack F Vogel #define IXGBE_WRITE_REG_BE32(a, reg, value) \
17161a4e3449SJack F Vogel 	IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(IXGBE_NTOHL(value)))
17171a4e3449SJack F Vogel 
17181a4e3449SJack F Vogel #define IXGBE_STORE_AS_BE16(_value) \
171985d0a26eSJack F Vogel 	IXGBE_NTOHS(((u16)(_value) >> 8) | ((u16)(_value) << 8))
17201a4e3449SJack F Vogel 
ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw * hw,union ixgbe_atr_input * input_mask,bool cloud_mode)172185d0a26eSJack F Vogel s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
1722758cc3dcSJack F Vogel 				    union ixgbe_atr_input *input_mask, bool cloud_mode)
1723770e416bSJack F Vogel {
172485d0a26eSJack F Vogel 	/* mask IPv6 since it is currently not supported */
172585d0a26eSJack F Vogel 	u32 fdirm = IXGBE_FDIRM_DIPv6;
172685d0a26eSJack F Vogel 	u32 fdirtcpm;
1727758cc3dcSJack F Vogel 	u32 fdirip6m;
17287d48aa4cSEric Joyner 	UNREFERENCED_1PARAMETER(cloud_mode);
172985d0a26eSJack F Vogel 	DEBUGFUNC("ixgbe_fdir_set_atr_input_mask_82599");
1730770e416bSJack F Vogel 
1731c0014855SJack F Vogel 	/*
1732c0014855SJack F Vogel 	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
1733c0014855SJack F Vogel 	 * are zero, then assume a full mask for that field.  Also assume that
1734c0014855SJack F Vogel 	 * a VLAN of 0 is unspecified, so mask that out as well.  L4type
1735c0014855SJack F Vogel 	 * cannot be masked out in this implementation.
1736c0014855SJack F Vogel 	 *
1737c0014855SJack F Vogel 	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
1738c0014855SJack F Vogel 	 * point in time.
1739c0014855SJack F Vogel 	 */
1740c0014855SJack F Vogel 
174185d0a26eSJack F Vogel 	/* verify bucket hash is cleared on hash generation */
174285d0a26eSJack F Vogel 	if (input_mask->formatted.bkt_hash)
174385d0a26eSJack F Vogel 		DEBUGOUT(" bucket hash should always be 0 in mask\n");
174485d0a26eSJack F Vogel 
174585d0a26eSJack F Vogel 	/* Program FDIRM and verify partial masks */
174685d0a26eSJack F Vogel 	switch (input_mask->formatted.vm_pool & 0x7F) {
174785d0a26eSJack F Vogel 	case 0x0:
174885d0a26eSJack F Vogel 		fdirm |= IXGBE_FDIRM_POOL;
174985d0a26eSJack F Vogel 	case 0x7F:
1750c0014855SJack F Vogel 		break;
175185d0a26eSJack F Vogel 	default:
175285d0a26eSJack F Vogel 		DEBUGOUT(" Error on vm pool mask\n");
175385d0a26eSJack F Vogel 		return IXGBE_ERR_CONFIG;
175485d0a26eSJack F Vogel 	}
175585d0a26eSJack F Vogel 
175685d0a26eSJack F Vogel 	switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) {
175785d0a26eSJack F Vogel 	case 0x0:
175885d0a26eSJack F Vogel 		fdirm |= IXGBE_FDIRM_L4P;
175985d0a26eSJack F Vogel 		if (input_mask->formatted.dst_port ||
176085d0a26eSJack F Vogel 		    input_mask->formatted.src_port) {
176185d0a26eSJack F Vogel 			DEBUGOUT(" Error on src/dst port mask\n");
176285d0a26eSJack F Vogel 			return IXGBE_ERR_CONFIG;
176385d0a26eSJack F Vogel 		}
176485d0a26eSJack F Vogel 	case IXGBE_ATR_L4TYPE_MASK:
17651a4e3449SJack F Vogel 		break;
176685d0a26eSJack F Vogel 	default:
176785d0a26eSJack F Vogel 		DEBUGOUT(" Error on flow type mask\n");
176885d0a26eSJack F Vogel 		return IXGBE_ERR_CONFIG;
176985d0a26eSJack F Vogel 	}
177085d0a26eSJack F Vogel 
177185d0a26eSJack F Vogel 	switch (IXGBE_NTOHS(input_mask->formatted.vlan_id) & 0xEFFF) {
17721a4e3449SJack F Vogel 	case 0x0000:
17738eb6488eSEric Joyner 		/* mask VLAN ID */
177485d0a26eSJack F Vogel 		fdirm |= IXGBE_FDIRM_VLANID;
177550455f73SPiotr Skajewski 		/* mask VLAN priority */
177650455f73SPiotr Skajewski 		fdirm |= IXGBE_FDIRM_VLANP;
177750455f73SPiotr Skajewski 		break;
177885d0a26eSJack F Vogel 	case 0x0FFF:
177985d0a26eSJack F Vogel 		/* mask VLAN priority */
178085d0a26eSJack F Vogel 		fdirm |= IXGBE_FDIRM_VLANP;
178185d0a26eSJack F Vogel 		break;
178285d0a26eSJack F Vogel 	case 0xE000:
17838eb6488eSEric Joyner 		/* mask VLAN ID only */
178485d0a26eSJack F Vogel 		fdirm |= IXGBE_FDIRM_VLANID;
17858eb6488eSEric Joyner 		/* fall through */
178685d0a26eSJack F Vogel 	case 0xEFFF:
178785d0a26eSJack F Vogel 		/* no VLAN fields masked */
1788c0014855SJack F Vogel 		break;
1789c0014855SJack F Vogel 	default:
17901a4e3449SJack F Vogel 		DEBUGOUT(" Error on VLAN mask\n");
17911a4e3449SJack F Vogel 		return IXGBE_ERR_CONFIG;
1792c0014855SJack F Vogel 	}
1793c0014855SJack F Vogel 
179485d0a26eSJack F Vogel 	switch (input_mask->formatted.flex_bytes & 0xFFFF) {
179585d0a26eSJack F Vogel 	case 0x0000:
17968eb6488eSEric Joyner 		/* Mask Flex Bytes */
179785d0a26eSJack F Vogel 		fdirm |= IXGBE_FDIRM_FLEX;
17988eb6488eSEric Joyner 		/* fall through */
179985d0a26eSJack F Vogel 	case 0xFFFF:
180085d0a26eSJack F Vogel 		break;
180185d0a26eSJack F Vogel 	default:
18021a4e3449SJack F Vogel 		DEBUGOUT(" Error on flexible byte mask\n");
18031a4e3449SJack F Vogel 		return IXGBE_ERR_CONFIG;
18041a4e3449SJack F Vogel 	}
1805c0014855SJack F Vogel 
1806758cc3dcSJack F Vogel 	if (cloud_mode) {
1807758cc3dcSJack F Vogel 		fdirm |= IXGBE_FDIRM_L3P;
1808758cc3dcSJack F Vogel 		fdirip6m = ((u32) 0xFFFFU << IXGBE_FDIRIP6M_DIPM_SHIFT);
1809758cc3dcSJack F Vogel 		fdirip6m |= IXGBE_FDIRIP6M_ALWAYS_MASK;
1810758cc3dcSJack F Vogel 
1811758cc3dcSJack F Vogel 		switch (input_mask->formatted.inner_mac[0] & 0xFF) {
1812758cc3dcSJack F Vogel 		case 0x00:
1813758cc3dcSJack F Vogel 			/* Mask inner MAC, fall through */
1814758cc3dcSJack F Vogel 			fdirip6m |= IXGBE_FDIRIP6M_INNER_MAC;
1815758cc3dcSJack F Vogel 		case 0xFF:
1816758cc3dcSJack F Vogel 			break;
1817758cc3dcSJack F Vogel 		default:
1818758cc3dcSJack F Vogel 			DEBUGOUT(" Error on inner_mac byte mask\n");
1819758cc3dcSJack F Vogel 			return IXGBE_ERR_CONFIG;
1820758cc3dcSJack F Vogel 		}
1821758cc3dcSJack F Vogel 
1822758cc3dcSJack F Vogel 		switch (input_mask->formatted.tni_vni & 0xFFFFFFFF) {
1823758cc3dcSJack F Vogel 		case 0x0:
1824758cc3dcSJack F Vogel 			/* Mask vxlan id */
1825758cc3dcSJack F Vogel 			fdirip6m |= IXGBE_FDIRIP6M_TNI_VNI;
1826758cc3dcSJack F Vogel 			break;
1827758cc3dcSJack F Vogel 		case 0x00FFFFFF:
1828758cc3dcSJack F Vogel 			fdirip6m |= IXGBE_FDIRIP6M_TNI_VNI_24;
1829758cc3dcSJack F Vogel 			break;
1830758cc3dcSJack F Vogel 		case 0xFFFFFFFF:
1831758cc3dcSJack F Vogel 			break;
1832758cc3dcSJack F Vogel 		default:
1833758cc3dcSJack F Vogel 			DEBUGOUT(" Error on TNI/VNI byte mask\n");
1834758cc3dcSJack F Vogel 			return IXGBE_ERR_CONFIG;
1835758cc3dcSJack F Vogel 		}
1836758cc3dcSJack F Vogel 
1837758cc3dcSJack F Vogel 		switch (input_mask->formatted.tunnel_type & 0xFFFF) {
1838758cc3dcSJack F Vogel 		case 0x0:
1839758cc3dcSJack F Vogel 			/* Mask turnnel type, fall through */
1840758cc3dcSJack F Vogel 			fdirip6m |= IXGBE_FDIRIP6M_TUNNEL_TYPE;
1841758cc3dcSJack F Vogel 		case 0xFFFF:
1842758cc3dcSJack F Vogel 			break;
1843758cc3dcSJack F Vogel 		default:
1844758cc3dcSJack F Vogel 			DEBUGOUT(" Error on tunnel type byte mask\n");
1845758cc3dcSJack F Vogel 			return IXGBE_ERR_CONFIG;
1846758cc3dcSJack F Vogel 		}
1847758cc3dcSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIP6M, fdirip6m);
1848758cc3dcSJack F Vogel 
18498eb6488eSEric Joyner 		/* Set all bits in FDIRTCPM, FDIRUDPM, FDIRSCTPM,
18508eb6488eSEric Joyner 		 * FDIRSIP4M and FDIRDIP4M in cloud mode to allow
18518eb6488eSEric Joyner 		 * L3/L3 packets to tunnel.
1852758cc3dcSJack F Vogel 		 */
1853758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xFFFFFFFF);
1854758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xFFFFFFFF);
1855758cc3dcSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M, 0xFFFFFFFF);
1856758cc3dcSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, 0xFFFFFFFF);
18578eb6488eSEric Joyner 		switch (hw->mac.type) {
18588eb6488eSEric Joyner 		case ixgbe_mac_X550:
18598eb6488eSEric Joyner 		case ixgbe_mac_X550EM_x:
18608eb6488eSEric Joyner 		case ixgbe_mac_X550EM_a:
18618eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, 0xFFFFFFFF);
18628eb6488eSEric Joyner 			break;
18638eb6488eSEric Joyner 		default:
18648eb6488eSEric Joyner 			break;
18658eb6488eSEric Joyner 		}
1866758cc3dcSJack F Vogel 	}
1867758cc3dcSJack F Vogel 
1868c0014855SJack F Vogel 	/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
1869c0014855SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
1870c0014855SJack F Vogel 
1871758cc3dcSJack F Vogel 	if (!cloud_mode) {
1872758cc3dcSJack F Vogel 		/* store the TCP/UDP port masks, bit reversed from port
1873758cc3dcSJack F Vogel 		 * layout */
187485d0a26eSJack F Vogel 		fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
18751a4e3449SJack F Vogel 
18761a4e3449SJack F Vogel 		/* write both the same so that UDP and TCP use the same mask */
18771a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
18781a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
1879758cc3dcSJack F Vogel 		/* also use it for SCTP */
1880758cc3dcSJack F Vogel 		switch (hw->mac.type) {
1881758cc3dcSJack F Vogel 		case ixgbe_mac_X550:
1882758cc3dcSJack F Vogel 		case ixgbe_mac_X550EM_x:
18838eb6488eSEric Joyner 		case ixgbe_mac_X550EM_a:
1884758cc3dcSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm);
1885758cc3dcSJack F Vogel 			break;
1886758cc3dcSJack F Vogel 		default:
1887758cc3dcSJack F Vogel 			break;
1888758cc3dcSJack F Vogel 		}
18891a4e3449SJack F Vogel 
18901a4e3449SJack F Vogel 		/* store source and destination IP masks (big-enian) */
18911a4e3449SJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
189285d0a26eSJack F Vogel 				     ~input_mask->formatted.src_ip[0]);
18931a4e3449SJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
189485d0a26eSJack F Vogel 				     ~input_mask->formatted.dst_ip[0]);
1895c4f73d5dSGuinan Sun 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIP6M, 0xFFFFFFFF);
1896758cc3dcSJack F Vogel 	}
189785d0a26eSJack F Vogel 	return IXGBE_SUCCESS;
189885d0a26eSJack F Vogel }
18991a4e3449SJack F Vogel 
ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw * hw,union ixgbe_atr_input * input,u16 soft_id,u8 queue,bool cloud_mode)190085d0a26eSJack F Vogel s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
190185d0a26eSJack F Vogel 					  union ixgbe_atr_input *input,
1902758cc3dcSJack F Vogel 					  u16 soft_id, u8 queue, bool cloud_mode)
190385d0a26eSJack F Vogel {
190485d0a26eSJack F Vogel 	u32 fdirport, fdirvlan, fdirhash, fdircmd;
1905758cc3dcSJack F Vogel 	u32 addr_low, addr_high;
1906758cc3dcSJack F Vogel 	u32 cloud_type = 0;
1907758cc3dcSJack F Vogel 	s32 err;
19087d48aa4cSEric Joyner 	UNREFERENCED_1PARAMETER(cloud_mode);
190985d0a26eSJack F Vogel 
191085d0a26eSJack F Vogel 	DEBUGFUNC("ixgbe_fdir_write_perfect_filter_82599");
1911758cc3dcSJack F Vogel 	if (!cloud_mode) {
191285d0a26eSJack F Vogel 		/* currently IPv6 is not supported, must be programmed with 0 */
191385d0a26eSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
191485d0a26eSJack F Vogel 				     input->formatted.src_ip[0]);
191585d0a26eSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
191685d0a26eSJack F Vogel 				     input->formatted.src_ip[1]);
191785d0a26eSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
191885d0a26eSJack F Vogel 				     input->formatted.src_ip[2]);
191985d0a26eSJack F Vogel 
192085d0a26eSJack F Vogel 		/* record the source address (big-endian) */
1921758cc3dcSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA,
1922758cc3dcSJack F Vogel 			input->formatted.src_ip[0]);
192385d0a26eSJack F Vogel 
1924758cc3dcSJack F Vogel 		/* record the first 32 bits of the destination address
1925758cc3dcSJack F Vogel 		 * (big-endian) */
1926758cc3dcSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA,
1927758cc3dcSJack F Vogel 			input->formatted.dst_ip[0]);
19281a4e3449SJack F Vogel 
19291a4e3449SJack F Vogel 		/* record source and destination port (little-endian)*/
19301a4e3449SJack F Vogel 		fdirport = IXGBE_NTOHS(input->formatted.dst_port);
19311a4e3449SJack F Vogel 		fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
1932994dd632SGuinan Sun 		fdirport |= (u32)IXGBE_NTOHS(input->formatted.src_port);
19331a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
1934758cc3dcSJack F Vogel 	}
19351a4e3449SJack F Vogel 
1936758cc3dcSJack F Vogel 	/* record VLAN (little-endian) and flex_bytes(big-endian) */
193785d0a26eSJack F Vogel 	fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes);
193885d0a26eSJack F Vogel 	fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
1939994dd632SGuinan Sun 	fdirvlan |= (u32)IXGBE_NTOHS(input->formatted.vlan_id);
194085d0a26eSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
19411a4e3449SJack F Vogel 
1942758cc3dcSJack F Vogel 	if (cloud_mode) {
1943758cc3dcSJack F Vogel 		if (input->formatted.tunnel_type != 0)
1944758cc3dcSJack F Vogel 			cloud_type = 0x80000000;
1945758cc3dcSJack F Vogel 
1946758cc3dcSJack F Vogel 		addr_low = ((u32)input->formatted.inner_mac[0] |
1947758cc3dcSJack F Vogel 				((u32)input->formatted.inner_mac[1] << 8) |
1948758cc3dcSJack F Vogel 				((u32)input->formatted.inner_mac[2] << 16) |
1949758cc3dcSJack F Vogel 				((u32)input->formatted.inner_mac[3] << 24));
1950758cc3dcSJack F Vogel 		addr_high = ((u32)input->formatted.inner_mac[4] |
1951758cc3dcSJack F Vogel 				((u32)input->formatted.inner_mac[5] << 8));
1952758cc3dcSJack F Vogel 		cloud_type |= addr_high;
1953758cc3dcSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0), addr_low);
1954758cc3dcSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1), cloud_type);
1955758cc3dcSJack F Vogel 		IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2), input->formatted.tni_vni);
1956758cc3dcSJack F Vogel 	}
1957758cc3dcSJack F Vogel 
195885d0a26eSJack F Vogel 	/* configure FDIRHASH register */
195985d0a26eSJack F Vogel 	fdirhash = input->formatted.bkt_hash;
196085d0a26eSJack F Vogel 	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
196185d0a26eSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
196285d0a26eSJack F Vogel 
196385d0a26eSJack F Vogel 	/*
196485d0a26eSJack F Vogel 	 * flush all previous writes to make certain registers are
196585d0a26eSJack F Vogel 	 * programmed prior to issuing the command
196685d0a26eSJack F Vogel 	 */
196785d0a26eSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
19681a4e3449SJack F Vogel 
1969182b3808SJack F Vogel 	/* configure FDIRCMD register */
1970182b3808SJack F Vogel 	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
1971182b3808SJack F Vogel 		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
197285d0a26eSJack F Vogel 	if (queue == IXGBE_FDIR_DROP_QUEUE)
197385d0a26eSJack F Vogel 		fdircmd |= IXGBE_FDIRCMD_DROP;
1974758cc3dcSJack F Vogel 	if (input->formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK)
1975758cc3dcSJack F Vogel 		fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER;
1976182b3808SJack F Vogel 	fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
1977182b3808SJack F Vogel 	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
197885d0a26eSJack F Vogel 	fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
19791a4e3449SJack F Vogel 
1980770e416bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
1981758cc3dcSJack F Vogel 	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
1982758cc3dcSJack F Vogel 	if (err) {
1983758cc3dcSJack F Vogel 		DEBUGOUT("Flow Director command did not complete!\n");
1984758cc3dcSJack F Vogel 		return err;
1985758cc3dcSJack F Vogel 	}
1986770e416bSJack F Vogel 
1987770e416bSJack F Vogel 	return IXGBE_SUCCESS;
1988770e416bSJack F Vogel }
1989770e416bSJack F Vogel 
ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw * hw,union ixgbe_atr_input * input,u16 soft_id)199085d0a26eSJack F Vogel s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
199185d0a26eSJack F Vogel 					  union ixgbe_atr_input *input,
199285d0a26eSJack F Vogel 					  u16 soft_id)
199385d0a26eSJack F Vogel {
199485d0a26eSJack F Vogel 	u32 fdirhash;
1995758cc3dcSJack F Vogel 	u32 fdircmd;
1996758cc3dcSJack F Vogel 	s32 err;
199785d0a26eSJack F Vogel 
199885d0a26eSJack F Vogel 	/* configure FDIRHASH register */
199985d0a26eSJack F Vogel 	fdirhash = input->formatted.bkt_hash;
200085d0a26eSJack F Vogel 	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
200185d0a26eSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
200285d0a26eSJack F Vogel 
200385d0a26eSJack F Vogel 	/* flush hash to HW */
200485d0a26eSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
200585d0a26eSJack F Vogel 
200685d0a26eSJack F Vogel 	/* Query if filter is present */
200785d0a26eSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
200885d0a26eSJack F Vogel 
2009758cc3dcSJack F Vogel 	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
2010758cc3dcSJack F Vogel 	if (err) {
2011758cc3dcSJack F Vogel 		DEBUGOUT("Flow Director command did not complete!\n");
2012758cc3dcSJack F Vogel 		return err;
201385d0a26eSJack F Vogel 	}
201485d0a26eSJack F Vogel 
201585d0a26eSJack F Vogel 	/* if filter exists in hardware then remove it */
201685d0a26eSJack F Vogel 	if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
201785d0a26eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
201885d0a26eSJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
201985d0a26eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
202085d0a26eSJack F Vogel 				IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
202185d0a26eSJack F Vogel 	}
202285d0a26eSJack F Vogel 
2023758cc3dcSJack F Vogel 	return IXGBE_SUCCESS;
202485d0a26eSJack F Vogel }
202585d0a26eSJack F Vogel 
202685d0a26eSJack F Vogel /**
202785d0a26eSJack F Vogel  * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
202885d0a26eSJack F Vogel  * @hw: pointer to hardware structure
202985d0a26eSJack F Vogel  * @input: input bitstream
203085d0a26eSJack F Vogel  * @input_mask: mask for the input bitstream
203185d0a26eSJack F Vogel  * @soft_id: software index for the filters
203285d0a26eSJack F Vogel  * @queue: queue index to direct traffic to
20337d48aa4cSEric Joyner  * @cloud_mode: unused
203485d0a26eSJack F Vogel  *
203585d0a26eSJack F Vogel  * Note that the caller to this function must lock before calling, since the
203685d0a26eSJack F Vogel  * hardware writes must be protected from one another.
203785d0a26eSJack F Vogel  **/
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)203885d0a26eSJack F Vogel s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
203985d0a26eSJack F Vogel 					union ixgbe_atr_input *input,
204085d0a26eSJack F Vogel 					union ixgbe_atr_input *input_mask,
2041758cc3dcSJack F Vogel 					u16 soft_id, u8 queue, bool cloud_mode)
204285d0a26eSJack F Vogel {
204385d0a26eSJack F Vogel 	s32 err = IXGBE_ERR_CONFIG;
20447d48aa4cSEric Joyner 	UNREFERENCED_1PARAMETER(cloud_mode);
204585d0a26eSJack F Vogel 
204685d0a26eSJack F Vogel 	DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599");
204785d0a26eSJack F Vogel 
204885d0a26eSJack F Vogel 	/*
204985d0a26eSJack F Vogel 	 * Check flow_type formatting, and bail out before we touch the hardware
205085d0a26eSJack F Vogel 	 * if there's a configuration issue
205185d0a26eSJack F Vogel 	 */
205285d0a26eSJack F Vogel 	switch (input->formatted.flow_type) {
205385d0a26eSJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_IPV4:
2054758cc3dcSJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_TUNNELED_IPV4:
205585d0a26eSJack F Vogel 		input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK;
205685d0a26eSJack F Vogel 		if (input->formatted.dst_port || input->formatted.src_port) {
205785d0a26eSJack F Vogel 			DEBUGOUT(" Error on src/dst port\n");
205885d0a26eSJack F Vogel 			return IXGBE_ERR_CONFIG;
205985d0a26eSJack F Vogel 		}
206085d0a26eSJack F Vogel 		break;
206185d0a26eSJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
2062758cc3dcSJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_TUNNELED_SCTPV4:
206385d0a26eSJack F Vogel 		if (input->formatted.dst_port || input->formatted.src_port) {
206485d0a26eSJack F Vogel 			DEBUGOUT(" Error on src/dst port\n");
206585d0a26eSJack F Vogel 			return IXGBE_ERR_CONFIG;
206685d0a26eSJack F Vogel 		}
206750455f73SPiotr Skajewski 		input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
206850455f73SPiotr Skajewski 						  IXGBE_ATR_L4TYPE_MASK;
206950455f73SPiotr Skajewski 		break;
207085d0a26eSJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_TCPV4:
2071758cc3dcSJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_TUNNELED_TCPV4:
207285d0a26eSJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_UDPV4:
2073758cc3dcSJack F Vogel 	case IXGBE_ATR_FLOW_TYPE_TUNNELED_UDPV4:
207485d0a26eSJack F Vogel 		input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
207585d0a26eSJack F Vogel 						  IXGBE_ATR_L4TYPE_MASK;
207685d0a26eSJack F Vogel 		break;
207785d0a26eSJack F Vogel 	default:
207885d0a26eSJack F Vogel 		DEBUGOUT(" Error on flow type input\n");
207985d0a26eSJack F Vogel 		return err;
208085d0a26eSJack F Vogel 	}
208185d0a26eSJack F Vogel 
208285d0a26eSJack F Vogel 	/* program input mask into the HW */
2083758cc3dcSJack F Vogel 	err = ixgbe_fdir_set_input_mask_82599(hw, input_mask, cloud_mode);
208485d0a26eSJack F Vogel 	if (err)
208585d0a26eSJack F Vogel 		return err;
208685d0a26eSJack F Vogel 
208785d0a26eSJack F Vogel 	/* apply mask and compute/store hash */
208885d0a26eSJack F Vogel 	ixgbe_atr_compute_perfect_hash_82599(input, input_mask);
208985d0a26eSJack F Vogel 
209085d0a26eSJack F Vogel 	/* program filters to filter memory */
209185d0a26eSJack F Vogel 	return ixgbe_fdir_write_perfect_filter_82599(hw, input,
2092758cc3dcSJack F Vogel 						     soft_id, queue, cloud_mode);
209385d0a26eSJack F Vogel }
209485d0a26eSJack F Vogel 
2095770e416bSJack F Vogel /**
2096770e416bSJack F Vogel  * ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
2097770e416bSJack F Vogel  * @hw: pointer to hardware structure
2098770e416bSJack F Vogel  * @reg: analog register to read
2099770e416bSJack F Vogel  * @val: read value
2100770e416bSJack F Vogel  *
2101770e416bSJack F Vogel  * Performs read operation to Omer analog register specified.
2102770e416bSJack F Vogel  **/
ixgbe_read_analog_reg8_82599(struct ixgbe_hw * hw,u32 reg,u8 * val)2103770e416bSJack F Vogel s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val)
2104770e416bSJack F Vogel {
2105770e416bSJack F Vogel 	u32  core_ctl;
2106770e416bSJack F Vogel 
21072969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_read_analog_reg8_82599");
21082969bf0eSJack F Vogel 
2109770e416bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD |
2110770e416bSJack F Vogel 			(reg << 8));
2111770e416bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
2112770e416bSJack F Vogel 	usec_delay(10);
2113770e416bSJack F Vogel 	core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL);
2114770e416bSJack F Vogel 	*val = (u8)core_ctl;
2115770e416bSJack F Vogel 
2116770e416bSJack F Vogel 	return IXGBE_SUCCESS;
2117770e416bSJack F Vogel }
2118770e416bSJack F Vogel 
2119770e416bSJack F Vogel /**
2120770e416bSJack F Vogel  * ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register
2121770e416bSJack F Vogel  * @hw: pointer to hardware structure
2122770e416bSJack F Vogel  * @reg: atlas register to write
2123770e416bSJack F Vogel  * @val: value to write
2124770e416bSJack F Vogel  *
2125770e416bSJack F Vogel  * Performs write operation to Omer analog register specified.
2126770e416bSJack F Vogel  **/
ixgbe_write_analog_reg8_82599(struct ixgbe_hw * hw,u32 reg,u8 val)2127770e416bSJack F Vogel s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val)
2128770e416bSJack F Vogel {
2129770e416bSJack F Vogel 	u32  core_ctl;
2130770e416bSJack F Vogel 
21312969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_write_analog_reg8_82599");
21322969bf0eSJack F Vogel 
2133770e416bSJack F Vogel 	core_ctl = (reg << 8) | val;
2134770e416bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl);
2135770e416bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
2136770e416bSJack F Vogel 	usec_delay(10);
2137770e416bSJack F Vogel 
2138770e416bSJack F Vogel 	return IXGBE_SUCCESS;
2139770e416bSJack F Vogel }
2140770e416bSJack F Vogel 
2141770e416bSJack F Vogel /**
214285d0a26eSJack F Vogel  * ixgbe_start_hw_82599 - Prepare hardware for Tx/Rx
2143770e416bSJack F Vogel  * @hw: pointer to hardware structure
2144770e416bSJack F Vogel  *
21451a4e3449SJack F Vogel  * Starts the hardware using the generic start_hw function
21461a4e3449SJack F Vogel  * and the generation start_hw function.
21471a4e3449SJack F Vogel  * Then performs revision-specific operations, if any.
2148770e416bSJack F Vogel  **/
ixgbe_start_hw_82599(struct ixgbe_hw * hw)214985d0a26eSJack F Vogel s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw)
2150770e416bSJack F Vogel {
2151770e416bSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
2152770e416bSJack F Vogel 
215385d0a26eSJack F Vogel 	DEBUGFUNC("ixgbe_start_hw_82599");
21542969bf0eSJack F Vogel 
2155770e416bSJack F Vogel 	ret_val = ixgbe_start_hw_generic(hw);
21561a4e3449SJack F Vogel 	if (ret_val != IXGBE_SUCCESS)
21571a4e3449SJack F Vogel 		goto out;
2158770e416bSJack F Vogel 
21593a890053SGuinan Sun 	ixgbe_start_hw_gen2(hw);
21602969bf0eSJack F Vogel 
2161d8602bb9SJack F Vogel 	/* We need to run link autotry after the driver loads */
216279b36ec9SKevin Bowling 	hw->mac.autotry_restart = true;
2163d8602bb9SJack F Vogel 
2164d8602bb9SJack F Vogel 	if (ret_val == IXGBE_SUCCESS)
2165d8602bb9SJack F Vogel 		ret_val = ixgbe_verify_fw_version_82599(hw);
21661a4e3449SJack F Vogel out:
2167770e416bSJack F Vogel 	return ret_val;
2168770e416bSJack F Vogel }
2169770e416bSJack F Vogel 
2170770e416bSJack F Vogel /**
2171770e416bSJack F Vogel  * ixgbe_identify_phy_82599 - Get physical layer module
2172770e416bSJack F Vogel  * @hw: pointer to hardware structure
2173770e416bSJack F Vogel  *
2174770e416bSJack F Vogel  * Determines the physical layer module found on the current adapter.
2175770e416bSJack F Vogel  * If PHY already detected, maintains current PHY type in hw struct,
2176770e416bSJack F Vogel  * otherwise executes the PHY detection routine.
2177770e416bSJack F Vogel  **/
ixgbe_identify_phy_82599(struct ixgbe_hw * hw)2178770e416bSJack F Vogel s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
2179770e416bSJack F Vogel {
2180758cc3dcSJack F Vogel 	s32 status;
2181770e416bSJack F Vogel 
21822969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_identify_phy_82599");
21832969bf0eSJack F Vogel 
2184770e416bSJack F Vogel 	/* Detect PHY if not unknown - returns success if already detected. */
2185770e416bSJack F Vogel 	status = ixgbe_identify_phy_generic(hw);
21861a4e3449SJack F Vogel 	if (status != IXGBE_SUCCESS) {
21871a4e3449SJack F Vogel 		/* 82599 10GBASE-T requires an external PHY */
21881a4e3449SJack F Vogel 		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
2189758cc3dcSJack F Vogel 			return status;
21901a4e3449SJack F Vogel 		else
219185d0a26eSJack F Vogel 			status = ixgbe_identify_module_generic(hw);
21921a4e3449SJack F Vogel 	}
21931a4e3449SJack F Vogel 
2194770e416bSJack F Vogel 	/* Set PHY type none if no PHY detected */
2195770e416bSJack F Vogel 	if (hw->phy.type == ixgbe_phy_unknown) {
2196770e416bSJack F Vogel 		hw->phy.type = ixgbe_phy_none;
2197758cc3dcSJack F Vogel 		return IXGBE_SUCCESS;
2198770e416bSJack F Vogel 	}
2199770e416bSJack F Vogel 
2200770e416bSJack F Vogel 	/* Return error if SFP module has been detected but is not supported */
2201770e416bSJack F Vogel 	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
2202758cc3dcSJack F Vogel 		return IXGBE_ERR_SFP_NOT_SUPPORTED;
2203770e416bSJack F Vogel 
2204770e416bSJack F Vogel 	return status;
2205770e416bSJack F Vogel }
2206770e416bSJack F Vogel 
2207770e416bSJack F Vogel /**
2208770e416bSJack F Vogel  * ixgbe_get_supported_physical_layer_82599 - Returns physical layer type
2209770e416bSJack F Vogel  * @hw: pointer to hardware structure
2210770e416bSJack F Vogel  *
2211770e416bSJack F Vogel  * Determines physical layer capabilities of the current configuration.
2212770e416bSJack F Vogel  **/
ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw * hw)22138eb6488eSEric Joyner u64 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
2214770e416bSJack F Vogel {
22158eb6488eSEric Joyner 	u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
2216770e416bSJack F Vogel 	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
2217770e416bSJack F Vogel 	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
2218770e416bSJack F Vogel 	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
2219770e416bSJack F Vogel 	u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
2220770e416bSJack F Vogel 	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
2221770e416bSJack F Vogel 	u16 ext_ability = 0;
2222770e416bSJack F Vogel 
22232969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_support_physical_layer_82599");
22242969bf0eSJack F Vogel 
2225770e416bSJack F Vogel 	hw->phy.ops.identify(hw);
2226770e416bSJack F Vogel 
22271a4e3449SJack F Vogel 	switch (hw->phy.type) {
22281a4e3449SJack F Vogel 	case ixgbe_phy_tn:
22291a4e3449SJack F Vogel 	case ixgbe_phy_cu_unknown:
2230770e416bSJack F Vogel 		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
2231770e416bSJack F Vogel 		IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
2232770e416bSJack F Vogel 		if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
2233770e416bSJack F Vogel 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
2234770e416bSJack F Vogel 		if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
2235770e416bSJack F Vogel 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
2236770e416bSJack F Vogel 		if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
2237770e416bSJack F Vogel 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
2238770e416bSJack F Vogel 		goto out;
22391a4e3449SJack F Vogel 	default:
22401a4e3449SJack F Vogel 		break;
2241770e416bSJack F Vogel 	}
2242770e416bSJack F Vogel 
2243770e416bSJack F Vogel 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
2244770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_1G_AN:
2245770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
2246770e416bSJack F Vogel 		if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) {
2247770e416bSJack F Vogel 			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
2248770e416bSJack F Vogel 			    IXGBE_PHYSICAL_LAYER_1000BASE_BX;
2249770e416bSJack F Vogel 			goto out;
2250770e416bSJack F Vogel 		} else
2251770e416bSJack F Vogel 			/* SFI mode so read SFP module */
2252770e416bSJack F Vogel 			goto sfp_check;
2253770e416bSJack F Vogel 		break;
2254770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
2255770e416bSJack F Vogel 		if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4)
2256770e416bSJack F Vogel 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
2257770e416bSJack F Vogel 		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4)
2258770e416bSJack F Vogel 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
2259d8602bb9SJack F Vogel 		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI)
2260d8602bb9SJack F Vogel 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI;
2261770e416bSJack F Vogel 		goto out;
2262770e416bSJack F Vogel 		break;
2263770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_10G_SERIAL:
2264770e416bSJack F Vogel 		if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) {
2265770e416bSJack F Vogel 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR;
2266770e416bSJack F Vogel 			goto out;
2267770e416bSJack F Vogel 		} else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)
2268770e416bSJack F Vogel 			goto sfp_check;
2269770e416bSJack F Vogel 		break;
2270770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
2271770e416bSJack F Vogel 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
2272770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KX_SUPP)
2273770e416bSJack F Vogel 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
2274770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
2275770e416bSJack F Vogel 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
2276770e416bSJack F Vogel 		if (autoc & IXGBE_AUTOC_KR_SUPP)
2277770e416bSJack F Vogel 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
2278770e416bSJack F Vogel 		goto out;
2279770e416bSJack F Vogel 		break;
2280770e416bSJack F Vogel 	default:
2281770e416bSJack F Vogel 		goto out;
2282770e416bSJack F Vogel 		break;
2283770e416bSJack F Vogel 	}
2284770e416bSJack F Vogel 
2285770e416bSJack F Vogel sfp_check:
2286770e416bSJack F Vogel 	/* SFP check must be done last since DA modules are sometimes used to
2287770e416bSJack F Vogel 	 * test KR mode -  we need to id KR mode correctly before SFP module.
2288770e416bSJack F Vogel 	 * Call identify_sfp because the pluggable module may have changed */
2289758cc3dcSJack F Vogel 	physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw);
2290770e416bSJack F Vogel out:
2291770e416bSJack F Vogel 	return physical_layer;
2292770e416bSJack F Vogel }
2293770e416bSJack F Vogel 
2294770e416bSJack F Vogel /**
2295770e416bSJack F Vogel  * ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599
2296770e416bSJack F Vogel  * @hw: pointer to hardware structure
2297770e416bSJack F Vogel  * @regval: register value to write to RXCTRL
2298770e416bSJack F Vogel  *
2299770e416bSJack F Vogel  * Enables the Rx DMA unit for 82599
2300770e416bSJack F Vogel  **/
ixgbe_enable_rx_dma_82599(struct ixgbe_hw * hw,u32 regval)2301770e416bSJack F Vogel s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
2302770e416bSJack F Vogel {
2303770e416bSJack F Vogel 
23042969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_enable_rx_dma_82599");
23052969bf0eSJack F Vogel 
2306770e416bSJack F Vogel 	/*
2307770e416bSJack F Vogel 	 * Workaround for 82599 silicon errata when enabling the Rx datapath.
2308770e416bSJack F Vogel 	 * If traffic is incoming before we enable the Rx unit, it could hang
2309770e416bSJack F Vogel 	 * the Rx DMA unit.  Therefore, make sure the security engine is
2310770e416bSJack F Vogel 	 * completely disabled prior to enabling the Rx unit.
2311770e416bSJack F Vogel 	 */
2312770e416bSJack F Vogel 
231385d0a26eSJack F Vogel 	hw->mac.ops.disable_sec_rx_path(hw);
2314770e416bSJack F Vogel 
2315758cc3dcSJack F Vogel 	if (regval & IXGBE_RXCTRL_RXEN)
2316758cc3dcSJack F Vogel 		ixgbe_enable_rx(hw);
2317758cc3dcSJack F Vogel 	else
2318758cc3dcSJack F Vogel 		ixgbe_disable_rx(hw);
231985d0a26eSJack F Vogel 
232085d0a26eSJack F Vogel 	hw->mac.ops.enable_sec_rx_path(hw);
2321770e416bSJack F Vogel 
2322770e416bSJack F Vogel 	return IXGBE_SUCCESS;
2323770e416bSJack F Vogel }
2324770e416bSJack F Vogel 
2325770e416bSJack F Vogel /**
2326758cc3dcSJack F Vogel  * ixgbe_verify_fw_version_82599 - verify FW version for 82599
2327d8602bb9SJack F Vogel  * @hw: pointer to hardware structure
2328d8602bb9SJack F Vogel  *
2329d8602bb9SJack F Vogel  * Verifies that installed the firmware version is 0.6 or higher
2330d8602bb9SJack F Vogel  * for SFI devices. All 82599 SFI devices should have version 0.6 or higher.
2331d8602bb9SJack F Vogel  *
2332d8602bb9SJack F Vogel  * Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or
2333d8602bb9SJack F Vogel  * if the FW version is not supported.
2334d8602bb9SJack F Vogel  **/
ixgbe_verify_fw_version_82599(struct ixgbe_hw * hw)2335fd75b91dSJack F Vogel static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
2336d8602bb9SJack F Vogel {
2337d8602bb9SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM_VERSION;
2338d8602bb9SJack F Vogel 	u16 fw_offset, fw_ptp_cfg_offset;
2339fd75b91dSJack F Vogel 	u16 fw_version;
2340d8602bb9SJack F Vogel 
23412969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_verify_fw_version_82599");
23422969bf0eSJack F Vogel 
2343d8602bb9SJack F Vogel 	/* firmware check is only necessary for SFI devices */
2344d8602bb9SJack F Vogel 	if (hw->phy.media_type != ixgbe_media_type_fiber) {
2345d8602bb9SJack F Vogel 		status = IXGBE_SUCCESS;
2346d8602bb9SJack F Vogel 		goto fw_version_out;
2347d8602bb9SJack F Vogel 	}
2348d8602bb9SJack F Vogel 
2349d8602bb9SJack F Vogel 	/* get the offset to the Firmware Module block */
2350fd75b91dSJack F Vogel 	if (hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset)) {
2351fd75b91dSJack F Vogel 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
2352fd75b91dSJack F Vogel 			      "eeprom read at offset %d failed", IXGBE_FW_PTR);
2353fd75b91dSJack F Vogel 		return IXGBE_ERR_EEPROM_VERSION;
2354fd75b91dSJack F Vogel 	}
2355d8602bb9SJack F Vogel 
2356d8602bb9SJack F Vogel 	if ((fw_offset == 0) || (fw_offset == 0xFFFF))
2357d8602bb9SJack F Vogel 		goto fw_version_out;
2358d8602bb9SJack F Vogel 
2359d8602bb9SJack F Vogel 	/* get the offset to the Pass Through Patch Configuration block */
2360fd75b91dSJack F Vogel 	if (hw->eeprom.ops.read(hw, (fw_offset +
2361d8602bb9SJack F Vogel 				 IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR),
2362fd75b91dSJack F Vogel 				 &fw_ptp_cfg_offset)) {
2363fd75b91dSJack F Vogel 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
2364fd75b91dSJack F Vogel 			      "eeprom read at offset %d failed",
2365fd75b91dSJack F Vogel 			      fw_offset +
2366fd75b91dSJack F Vogel 			      IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR);
2367fd75b91dSJack F Vogel 		return IXGBE_ERR_EEPROM_VERSION;
2368fd75b91dSJack F Vogel 	}
2369d8602bb9SJack F Vogel 
2370d8602bb9SJack F Vogel 	if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
2371d8602bb9SJack F Vogel 		goto fw_version_out;
2372d8602bb9SJack F Vogel 
2373d8602bb9SJack F Vogel 	/* get the firmware version */
2374fd75b91dSJack F Vogel 	if (hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset +
2375fd75b91dSJack F Vogel 			    IXGBE_FW_PATCH_VERSION_4), &fw_version)) {
2376fd75b91dSJack F Vogel 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
2377fd75b91dSJack F Vogel 			      "eeprom read at offset %d failed",
2378fd75b91dSJack F Vogel 			      fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4);
2379fd75b91dSJack F Vogel 		return IXGBE_ERR_EEPROM_VERSION;
2380fd75b91dSJack F Vogel 	}
2381d8602bb9SJack F Vogel 
2382d8602bb9SJack F Vogel 	if (fw_version > 0x5)
2383d8602bb9SJack F Vogel 		status = IXGBE_SUCCESS;
2384d8602bb9SJack F Vogel 
2385d8602bb9SJack F Vogel fw_version_out:
2386d8602bb9SJack F Vogel 	return status;
2387d8602bb9SJack F Vogel }
2388182b3808SJack F Vogel 
2389c0014855SJack F Vogel /**
2390182b3808SJack F Vogel  * ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state.
2391c0014855SJack F Vogel  * @hw: pointer to hardware structure
2392c0014855SJack F Vogel  *
239379b36ec9SKevin Bowling  * Returns true if the LESM FW module is present and enabled. Otherwise
239479b36ec9SKevin Bowling  * returns false. Smart Speed must be disabled if LESM FW module is enabled.
2395c0014855SJack F Vogel  **/
ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw * hw)2396182b3808SJack F Vogel bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
2397c0014855SJack F Vogel {
239879b36ec9SKevin Bowling 	bool lesm_enabled = false;
2399182b3808SJack F Vogel 	u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
2400182b3808SJack F Vogel 	s32 status;
2401c0014855SJack F Vogel 
2402182b3808SJack F Vogel 	DEBUGFUNC("ixgbe_verify_lesm_fw_enabled_82599");
2403c0014855SJack F Vogel 
2404182b3808SJack F Vogel 	/* get the offset to the Firmware Module block */
2405182b3808SJack F Vogel 	status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
2406182b3808SJack F Vogel 
2407182b3808SJack F Vogel 	if ((status != IXGBE_SUCCESS) ||
2408182b3808SJack F Vogel 	    (fw_offset == 0) || (fw_offset == 0xFFFF))
2409182b3808SJack F Vogel 		goto out;
2410182b3808SJack F Vogel 
2411182b3808SJack F Vogel 	/* get the offset to the LESM Parameters block */
2412182b3808SJack F Vogel 	status = hw->eeprom.ops.read(hw, (fw_offset +
2413182b3808SJack F Vogel 				     IXGBE_FW_LESM_PARAMETERS_PTR),
2414182b3808SJack F Vogel 				     &fw_lesm_param_offset);
2415182b3808SJack F Vogel 
2416182b3808SJack F Vogel 	if ((status != IXGBE_SUCCESS) ||
2417182b3808SJack F Vogel 	    (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF))
2418182b3808SJack F Vogel 		goto out;
2419182b3808SJack F Vogel 
2420758cc3dcSJack F Vogel 	/* get the LESM state word */
2421182b3808SJack F Vogel 	status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset +
2422182b3808SJack F Vogel 				     IXGBE_FW_LESM_STATE_1),
2423182b3808SJack F Vogel 				     &fw_lesm_state);
2424182b3808SJack F Vogel 
2425182b3808SJack F Vogel 	if ((status == IXGBE_SUCCESS) &&
2426182b3808SJack F Vogel 	    (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
242779b36ec9SKevin Bowling 		lesm_enabled = true;
2428182b3808SJack F Vogel 
2429182b3808SJack F Vogel out:
2430182b3808SJack F Vogel 	return lesm_enabled;
2431c0014855SJack F Vogel }
2432c0014855SJack F Vogel 
243385d0a26eSJack F Vogel /**
243485d0a26eSJack F Vogel  * ixgbe_read_eeprom_buffer_82599 - Read EEPROM word(s) using
243585d0a26eSJack F Vogel  * fastest available method
243685d0a26eSJack F Vogel  *
243785d0a26eSJack F Vogel  * @hw: pointer to hardware structure
243885d0a26eSJack F Vogel  * @offset: offset of  word in EEPROM to read
243985d0a26eSJack F Vogel  * @words: number of words
244085d0a26eSJack F Vogel  * @data: word(s) read from the EEPROM
244185d0a26eSJack F Vogel  *
244285d0a26eSJack F Vogel  * Retrieves 16 bit word(s) read from EEPROM
244385d0a26eSJack F Vogel  **/
ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)244485d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
244585d0a26eSJack F Vogel 					  u16 words, u16 *data)
244685d0a26eSJack F Vogel {
244785d0a26eSJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
244885d0a26eSJack F Vogel 	s32 ret_val = IXGBE_ERR_CONFIG;
244985d0a26eSJack F Vogel 
245085d0a26eSJack F Vogel 	DEBUGFUNC("ixgbe_read_eeprom_buffer_82599");
245185d0a26eSJack F Vogel 
245285d0a26eSJack F Vogel 	/*
245385d0a26eSJack F Vogel 	 * If EEPROM is detected and can be addressed using 14 bits,
245485d0a26eSJack F Vogel 	 * use EERD otherwise use bit bang
245585d0a26eSJack F Vogel 	 */
245685d0a26eSJack F Vogel 	if ((eeprom->type == ixgbe_eeprom_spi) &&
245785d0a26eSJack F Vogel 	    (offset + (words - 1) <= IXGBE_EERD_MAX_ADDR))
245885d0a26eSJack F Vogel 		ret_val = ixgbe_read_eerd_buffer_generic(hw, offset, words,
245985d0a26eSJack F Vogel 							 data);
246085d0a26eSJack F Vogel 	else
246185d0a26eSJack F Vogel 		ret_val = ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset,
246285d0a26eSJack F Vogel 								    words,
246385d0a26eSJack F Vogel 								    data);
246485d0a26eSJack F Vogel 
246585d0a26eSJack F Vogel 	return ret_val;
246685d0a26eSJack F Vogel }
246785d0a26eSJack F Vogel 
246885d0a26eSJack F Vogel /**
246985d0a26eSJack F Vogel  * ixgbe_read_eeprom_82599 - Read EEPROM word using
247085d0a26eSJack F Vogel  * fastest available method
247185d0a26eSJack F Vogel  *
247285d0a26eSJack F Vogel  * @hw: pointer to hardware structure
247385d0a26eSJack F Vogel  * @offset: offset of  word in the EEPROM to read
247485d0a26eSJack F Vogel  * @data: word read from the EEPROM
247585d0a26eSJack F Vogel  *
247685d0a26eSJack F Vogel  * Reads a 16 bit word from the EEPROM
247785d0a26eSJack F Vogel  **/
ixgbe_read_eeprom_82599(struct ixgbe_hw * hw,u16 offset,u16 * data)247885d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
247985d0a26eSJack F Vogel 				   u16 offset, u16 *data)
248085d0a26eSJack F Vogel {
248185d0a26eSJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
248285d0a26eSJack F Vogel 	s32 ret_val = IXGBE_ERR_CONFIG;
248385d0a26eSJack F Vogel 
248485d0a26eSJack F Vogel 	DEBUGFUNC("ixgbe_read_eeprom_82599");
248585d0a26eSJack F Vogel 
248685d0a26eSJack F Vogel 	/*
248785d0a26eSJack F Vogel 	 * If EEPROM is detected and can be addressed using 14 bits,
248885d0a26eSJack F Vogel 	 * use EERD otherwise use bit bang
248985d0a26eSJack F Vogel 	 */
249085d0a26eSJack F Vogel 	if ((eeprom->type == ixgbe_eeprom_spi) &&
249185d0a26eSJack F Vogel 	    (offset <= IXGBE_EERD_MAX_ADDR))
249285d0a26eSJack F Vogel 		ret_val = ixgbe_read_eerd_generic(hw, offset, data);
249385d0a26eSJack F Vogel 	else
249485d0a26eSJack F Vogel 		ret_val = ixgbe_read_eeprom_bit_bang_generic(hw, offset, data);
249585d0a26eSJack F Vogel 
249685d0a26eSJack F Vogel 	return ret_val;
249785d0a26eSJack F Vogel }
2498c0014855SJack F Vogel 
24990ecc2ff0SJack F Vogel /**
25000ecc2ff0SJack F Vogel  * ixgbe_reset_pipeline_82599 - perform pipeline reset
25010ecc2ff0SJack F Vogel  *
25020ecc2ff0SJack F Vogel  * @hw: pointer to hardware structure
25030ecc2ff0SJack F Vogel  *
25040ecc2ff0SJack F Vogel  * Reset pipeline by asserting Restart_AN together with LMS change to ensure
2505758cc3dcSJack F Vogel  * full pipeline reset.  This function assumes the SW/FW lock is held.
25060ecc2ff0SJack F Vogel  **/
ixgbe_reset_pipeline_82599(struct ixgbe_hw * hw)25070ecc2ff0SJack F Vogel s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
25080ecc2ff0SJack F Vogel {
25090ecc2ff0SJack F Vogel 	s32 ret_val;
25100ecc2ff0SJack F Vogel 	u32 anlp1_reg = 0;
25110ecc2ff0SJack F Vogel 	u32 i, autoc_reg, autoc2_reg;
25120ecc2ff0SJack F Vogel 
25130ecc2ff0SJack F Vogel 	/* Enable link if disabled in NVM */
25140ecc2ff0SJack F Vogel 	autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
25150ecc2ff0SJack F Vogel 	if (autoc2_reg & IXGBE_AUTOC2_LINK_DISABLE_MASK) {
25160ecc2ff0SJack F Vogel 		autoc2_reg &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK;
25170ecc2ff0SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
25180ecc2ff0SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
25190ecc2ff0SJack F Vogel 	}
25200ecc2ff0SJack F Vogel 
2521758cc3dcSJack F Vogel 	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
25220ecc2ff0SJack F Vogel 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
25230ecc2ff0SJack F Vogel 	/* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
2524758cc3dcSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
2525758cc3dcSJack F Vogel 			autoc_reg ^ (0x4 << IXGBE_AUTOC_LMS_SHIFT));
25260ecc2ff0SJack F Vogel 	/* Wait for AN to leave state 0 */
25270ecc2ff0SJack F Vogel 	for (i = 0; i < 10; i++) {
25280ecc2ff0SJack F Vogel 		msec_delay(4);
25290ecc2ff0SJack F Vogel 		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
25300ecc2ff0SJack F Vogel 		if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)
25310ecc2ff0SJack F Vogel 			break;
25320ecc2ff0SJack F Vogel 	}
25330ecc2ff0SJack F Vogel 
25340ecc2ff0SJack F Vogel 	if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
25350ecc2ff0SJack F Vogel 		DEBUGOUT("auto negotiation not completed\n");
25360ecc2ff0SJack F Vogel 		ret_val = IXGBE_ERR_RESET_FAILED;
25370ecc2ff0SJack F Vogel 		goto reset_pipeline_out;
25380ecc2ff0SJack F Vogel 	}
25390ecc2ff0SJack F Vogel 
25400ecc2ff0SJack F Vogel 	ret_val = IXGBE_SUCCESS;
25410ecc2ff0SJack F Vogel 
25420ecc2ff0SJack F Vogel reset_pipeline_out:
25430ecc2ff0SJack F Vogel 	/* Write AUTOC register with original LMS field and Restart_AN */
25440ecc2ff0SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
25450ecc2ff0SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
25460ecc2ff0SJack F Vogel 
25470ecc2ff0SJack F Vogel 	return ret_val;
25480ecc2ff0SJack F Vogel }
25490ecc2ff0SJack F Vogel 
2550758cc3dcSJack F Vogel /**
2551758cc3dcSJack F Vogel  * ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C
2552758cc3dcSJack F Vogel  * @hw: pointer to hardware structure
2553758cc3dcSJack F Vogel  * @byte_offset: byte offset to read
25547d48aa4cSEric Joyner  * @dev_addr: address to read from
2555758cc3dcSJack F Vogel  * @data: value read
2556758cc3dcSJack F Vogel  *
2557758cc3dcSJack F Vogel  * Performs byte read operation to SFP module's EEPROM over I2C interface at
2558758cc3dcSJack F Vogel  * a specified device address.
2559758cc3dcSJack F Vogel  **/
ixgbe_read_i2c_byte_82599(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 * data)2560758cc3dcSJack F Vogel static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
2561758cc3dcSJack F Vogel 				u8 dev_addr, u8 *data)
2562758cc3dcSJack F Vogel {
2563758cc3dcSJack F Vogel 	u32 esdp;
2564758cc3dcSJack F Vogel 	s32 status;
2565758cc3dcSJack F Vogel 	s32 timeout = 200;
2566a621e3c8SJack F Vogel 
2567758cc3dcSJack F Vogel 	DEBUGFUNC("ixgbe_read_i2c_byte_82599");
2568758cc3dcSJack F Vogel 
256979b36ec9SKevin Bowling 	if (hw->phy.qsfp_shared_i2c_bus == true) {
2570758cc3dcSJack F Vogel 		/* Acquire I2C bus ownership. */
2571758cc3dcSJack F Vogel 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2572758cc3dcSJack F Vogel 		esdp |= IXGBE_ESDP_SDP0;
2573758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
2574758cc3dcSJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
2575758cc3dcSJack F Vogel 
2576758cc3dcSJack F Vogel 		while (timeout) {
2577758cc3dcSJack F Vogel 			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2578758cc3dcSJack F Vogel 			if (esdp & IXGBE_ESDP_SDP1)
2579758cc3dcSJack F Vogel 				break;
2580758cc3dcSJack F Vogel 
2581758cc3dcSJack F Vogel 			msec_delay(5);
2582758cc3dcSJack F Vogel 			timeout--;
2583758cc3dcSJack F Vogel 		}
2584758cc3dcSJack F Vogel 
2585758cc3dcSJack F Vogel 		if (!timeout) {
2586758cc3dcSJack F Vogel 			DEBUGOUT("Driver can't access resource,"
2587758cc3dcSJack F Vogel 				 " acquiring I2C bus timeout.\n");
2588758cc3dcSJack F Vogel 			status = IXGBE_ERR_I2C;
2589758cc3dcSJack F Vogel 			goto release_i2c_access;
2590758cc3dcSJack F Vogel 		}
2591758cc3dcSJack F Vogel 	}
2592758cc3dcSJack F Vogel 
2593758cc3dcSJack F Vogel 	status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data);
2594758cc3dcSJack F Vogel 
2595758cc3dcSJack F Vogel release_i2c_access:
2596758cc3dcSJack F Vogel 
259779b36ec9SKevin Bowling 	if (hw->phy.qsfp_shared_i2c_bus == true) {
2598758cc3dcSJack F Vogel 		/* Release I2C bus ownership. */
2599758cc3dcSJack F Vogel 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2600758cc3dcSJack F Vogel 		esdp &= ~IXGBE_ESDP_SDP0;
2601758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
2602758cc3dcSJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
2603758cc3dcSJack F Vogel 	}
2604758cc3dcSJack F Vogel 
2605758cc3dcSJack F Vogel 	return status;
2606758cc3dcSJack F Vogel }
2607758cc3dcSJack F Vogel 
2608758cc3dcSJack F Vogel /**
2609758cc3dcSJack F Vogel  * ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C
2610758cc3dcSJack F Vogel  * @hw: pointer to hardware structure
2611758cc3dcSJack F Vogel  * @byte_offset: byte offset to write
26127d48aa4cSEric Joyner  * @dev_addr: address to read from
2613758cc3dcSJack F Vogel  * @data: value to write
2614758cc3dcSJack F Vogel  *
2615758cc3dcSJack F Vogel  * Performs byte write operation to SFP module's EEPROM over I2C interface at
2616758cc3dcSJack F Vogel  * a specified device address.
2617758cc3dcSJack F Vogel  **/
ixgbe_write_i2c_byte_82599(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 data)2618758cc3dcSJack F Vogel static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
2619758cc3dcSJack F Vogel 				 u8 dev_addr, u8 data)
2620758cc3dcSJack F Vogel {
2621758cc3dcSJack F Vogel 	u32 esdp;
2622758cc3dcSJack F Vogel 	s32 status;
2623758cc3dcSJack F Vogel 	s32 timeout = 200;
2624758cc3dcSJack F Vogel 
2625758cc3dcSJack F Vogel 	DEBUGFUNC("ixgbe_write_i2c_byte_82599");
2626758cc3dcSJack F Vogel 
262779b36ec9SKevin Bowling 	if (hw->phy.qsfp_shared_i2c_bus == true) {
2628758cc3dcSJack F Vogel 		/* Acquire I2C bus ownership. */
2629758cc3dcSJack F Vogel 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2630758cc3dcSJack F Vogel 		esdp |= IXGBE_ESDP_SDP0;
2631758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
2632758cc3dcSJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
2633758cc3dcSJack F Vogel 
2634758cc3dcSJack F Vogel 		while (timeout) {
2635758cc3dcSJack F Vogel 			esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2636758cc3dcSJack F Vogel 			if (esdp & IXGBE_ESDP_SDP1)
2637758cc3dcSJack F Vogel 				break;
2638758cc3dcSJack F Vogel 
2639758cc3dcSJack F Vogel 			msec_delay(5);
2640758cc3dcSJack F Vogel 			timeout--;
2641758cc3dcSJack F Vogel 		}
2642758cc3dcSJack F Vogel 
2643758cc3dcSJack F Vogel 		if (!timeout) {
2644758cc3dcSJack F Vogel 			DEBUGOUT("Driver can't access resource,"
2645758cc3dcSJack F Vogel 				 " acquiring I2C bus timeout.\n");
2646758cc3dcSJack F Vogel 			status = IXGBE_ERR_I2C;
2647758cc3dcSJack F Vogel 			goto release_i2c_access;
2648758cc3dcSJack F Vogel 		}
2649758cc3dcSJack F Vogel 	}
2650758cc3dcSJack F Vogel 
2651758cc3dcSJack F Vogel 	status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data);
2652758cc3dcSJack F Vogel 
2653758cc3dcSJack F Vogel release_i2c_access:
2654758cc3dcSJack F Vogel 
265579b36ec9SKevin Bowling 	if (hw->phy.qsfp_shared_i2c_bus == true) {
2656758cc3dcSJack F Vogel 		/* Release I2C bus ownership. */
2657758cc3dcSJack F Vogel 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
2658758cc3dcSJack F Vogel 		esdp &= ~IXGBE_ESDP_SDP0;
2659758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
2660758cc3dcSJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
2661758cc3dcSJack F Vogel 	}
2662758cc3dcSJack F Vogel 
2663758cc3dcSJack F Vogel 	return status;
2664758cc3dcSJack F Vogel }
2665