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