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