xref: /onnv-gate/usr/src/uts/common/io/ixgbe/ixgbe_82599.c (revision 13006:22e6d3edaab5)
19353SSamuel.Tu@Sun.COM /*
29353SSamuel.Tu@Sun.COM  * CDDL HEADER START
39353SSamuel.Tu@Sun.COM  *
49353SSamuel.Tu@Sun.COM  * The contents of this file are subject to the terms of the
59353SSamuel.Tu@Sun.COM  * Common Development and Distribution License (the "License").
69353SSamuel.Tu@Sun.COM  * You may not use this file except in compliance with the License.
79353SSamuel.Tu@Sun.COM  *
89353SSamuel.Tu@Sun.COM  * You can obtain a copy of the license at:
99353SSamuel.Tu@Sun.COM  *      http://www.opensolaris.org/os/licensing.
109353SSamuel.Tu@Sun.COM  * See the License for the specific language governing permissions
119353SSamuel.Tu@Sun.COM  * and limitations under the License.
129353SSamuel.Tu@Sun.COM  *
139353SSamuel.Tu@Sun.COM  * When using or redistributing this file, you may do so under the
149353SSamuel.Tu@Sun.COM  * License only. No other modification of this header is permitted.
159353SSamuel.Tu@Sun.COM  *
169353SSamuel.Tu@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
179353SSamuel.Tu@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
189353SSamuel.Tu@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
199353SSamuel.Tu@Sun.COM  *
209353SSamuel.Tu@Sun.COM  * CDDL HEADER END
219353SSamuel.Tu@Sun.COM  */
229353SSamuel.Tu@Sun.COM 
239353SSamuel.Tu@Sun.COM /*
24*13006SChenlu.Chen@Sun.COM  * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
259353SSamuel.Tu@Sun.COM  */
269353SSamuel.Tu@Sun.COM 
27*13006SChenlu.Chen@Sun.COM /*
28*13006SChenlu.Chen@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
29*13006SChenlu.Chen@Sun.COM  */
30*13006SChenlu.Chen@Sun.COM 
31*13006SChenlu.Chen@Sun.COM /* IntelVersion: 1.217 scm_061610_003709 */
329353SSamuel.Tu@Sun.COM 
339353SSamuel.Tu@Sun.COM #include "ixgbe_type.h"
349353SSamuel.Tu@Sun.COM #include "ixgbe_api.h"
359353SSamuel.Tu@Sun.COM #include "ixgbe_common.h"
369353SSamuel.Tu@Sun.COM #include "ixgbe_phy.h"
379353SSamuel.Tu@Sun.COM 
389353SSamuel.Tu@Sun.COM s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw);
399353SSamuel.Tu@Sun.COM s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
409353SSamuel.Tu@Sun.COM     ixgbe_link_speed *speed, bool *autoneg);
419353SSamuel.Tu@Sun.COM enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw);
42*13006SChenlu.Chen@Sun.COM void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
43*13006SChenlu.Chen@Sun.COM void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
44*13006SChenlu.Chen@Sun.COM void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
4510998SChenlu.Chen@Sun.COM s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
4610998SChenlu.Chen@Sun.COM     ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete);
4710998SChenlu.Chen@Sun.COM s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
489353SSamuel.Tu@Sun.COM     ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete);
4910998SChenlu.Chen@Sun.COM s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
5010998SChenlu.Chen@Sun.COM     bool autoneg_wait_to_complete);
5110998SChenlu.Chen@Sun.COM s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
529353SSamuel.Tu@Sun.COM     ixgbe_link_speed speed, bool autoneg,
539353SSamuel.Tu@Sun.COM     bool autoneg_wait_to_complete);
5410998SChenlu.Chen@Sun.COM static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
559353SSamuel.Tu@Sun.COM     ixgbe_link_speed speed, bool autoneg,
569353SSamuel.Tu@Sun.COM     bool autoneg_wait_to_complete);
579353SSamuel.Tu@Sun.COM s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw);
589353SSamuel.Tu@Sun.COM void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw);
599353SSamuel.Tu@Sun.COM s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw);
609353SSamuel.Tu@Sun.COM s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val);
619353SSamuel.Tu@Sun.COM s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val);
629353SSamuel.Tu@Sun.COM s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw);
6312003SPaul.Guo@Sun.COM void ixgbe_enable_relaxed_ordering_82599(struct ixgbe_hw *hw);
649353SSamuel.Tu@Sun.COM s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw);
659353SSamuel.Tu@Sun.COM s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw);
669353SSamuel.Tu@Sun.COM u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
679353SSamuel.Tu@Sun.COM s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval);
689353SSamuel.Tu@Sun.COM s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps);
6910305SPaul.Guo@Sun.COM static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
709353SSamuel.Tu@Sun.COM 
719353SSamuel.Tu@Sun.COM void
ixgbe_init_mac_link_ops_82599(struct ixgbe_hw * hw)729353SSamuel.Tu@Sun.COM ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
739353SSamuel.Tu@Sun.COM {
749353SSamuel.Tu@Sun.COM 	struct ixgbe_mac_info *mac = &hw->mac;
759353SSamuel.Tu@Sun.COM 
769353SSamuel.Tu@Sun.COM 	DEBUGFUNC("ixgbe_init_mac_link_ops_82599");
779353SSamuel.Tu@Sun.COM 
789353SSamuel.Tu@Sun.COM 	if (hw->phy.multispeed_fiber) {
799353SSamuel.Tu@Sun.COM 		/* Set up dual speed SFP+ support */
8010998SChenlu.Chen@Sun.COM 		mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
81*13006SChenlu.Chen@Sun.COM 		mac->ops.disable_tx_laser =
82*13006SChenlu.Chen@Sun.COM 		    &ixgbe_disable_tx_laser_multispeed_fiber;
83*13006SChenlu.Chen@Sun.COM 		mac->ops.enable_tx_laser =
84*13006SChenlu.Chen@Sun.COM 		    &ixgbe_enable_tx_laser_multispeed_fiber;
85*13006SChenlu.Chen@Sun.COM 		mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber;
869353SSamuel.Tu@Sun.COM 	} else {
87*13006SChenlu.Chen@Sun.COM 		mac->ops.disable_tx_laser = NULL;
88*13006SChenlu.Chen@Sun.COM 		mac->ops.enable_tx_laser = NULL;
89*13006SChenlu.Chen@Sun.COM 		mac->ops.flap_tx_laser = NULL;
9010998SChenlu.Chen@Sun.COM 		if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) &&
9110998SChenlu.Chen@Sun.COM 		    (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
9210998SChenlu.Chen@Sun.COM 		    hw->phy.smart_speed == ixgbe_smart_speed_on))
9310998SChenlu.Chen@Sun.COM 			mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed;
9410998SChenlu.Chen@Sun.COM 		else
9510998SChenlu.Chen@Sun.COM 			mac->ops.setup_link = &ixgbe_setup_mac_link_82599;
969353SSamuel.Tu@Sun.COM 	}
979353SSamuel.Tu@Sun.COM }
989353SSamuel.Tu@Sun.COM 
999353SSamuel.Tu@Sun.COM /*
1009353SSamuel.Tu@Sun.COM  * ixgbe_init_phy_ops_82599 - PHY/SFP specific init
1019353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
1029353SSamuel.Tu@Sun.COM  *
1039353SSamuel.Tu@Sun.COM  * Initialize any function pointers that were not able to be
1049353SSamuel.Tu@Sun.COM  * set during init_shared_code because the PHY/SFP type was
1059353SSamuel.Tu@Sun.COM  * not known.  Perform the SFP init if necessary.
1069353SSamuel.Tu@Sun.COM  *
1079353SSamuel.Tu@Sun.COM  */
1089353SSamuel.Tu@Sun.COM s32
ixgbe_init_phy_ops_82599(struct ixgbe_hw * hw)1099353SSamuel.Tu@Sun.COM ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
1109353SSamuel.Tu@Sun.COM {
1119353SSamuel.Tu@Sun.COM 	struct ixgbe_mac_info *mac = &hw->mac;
1129353SSamuel.Tu@Sun.COM 	struct ixgbe_phy_info *phy = &hw->phy;
1139353SSamuel.Tu@Sun.COM 	s32 ret_val = IXGBE_SUCCESS;
1149353SSamuel.Tu@Sun.COM 
1159353SSamuel.Tu@Sun.COM 	DEBUGFUNC("ixgbe_init_phy_ops_82599");
1169353SSamuel.Tu@Sun.COM 
1179353SSamuel.Tu@Sun.COM 	/* Identify the PHY or SFP module */
1189353SSamuel.Tu@Sun.COM 	ret_val = phy->ops.identify(hw);
11910305SPaul.Guo@Sun.COM 	if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
12010305SPaul.Guo@Sun.COM 		goto init_phy_ops_out;
1219353SSamuel.Tu@Sun.COM 
1229353SSamuel.Tu@Sun.COM 	/* Setup function pointers based on detected SFP module and speeds */
1239353SSamuel.Tu@Sun.COM 	ixgbe_init_mac_link_ops_82599(hw);
1249353SSamuel.Tu@Sun.COM 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown)
1259353SSamuel.Tu@Sun.COM 		hw->phy.ops.reset = NULL;
1269353SSamuel.Tu@Sun.COM 
1279353SSamuel.Tu@Sun.COM 	/* If copper media, overwrite with copper function pointers */
1289353SSamuel.Tu@Sun.COM 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
1299353SSamuel.Tu@Sun.COM 		mac->ops.setup_link = &ixgbe_setup_copper_link_82599;
1309353SSamuel.Tu@Sun.COM 		mac->ops.get_link_capabilities =
1319353SSamuel.Tu@Sun.COM 		    &ixgbe_get_copper_link_capabilities_generic;
1329353SSamuel.Tu@Sun.COM 	}
1339353SSamuel.Tu@Sun.COM 
1349353SSamuel.Tu@Sun.COM 	/* Set necessary function pointers based on phy type */
1359353SSamuel.Tu@Sun.COM 	switch (hw->phy.type) {
1369353SSamuel.Tu@Sun.COM 	case ixgbe_phy_tn:
13712003SPaul.Guo@Sun.COM 		phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
1389353SSamuel.Tu@Sun.COM 		phy->ops.check_link = &ixgbe_check_phy_link_tnx;
1399353SSamuel.Tu@Sun.COM 		phy->ops.get_firmware_version =
1409353SSamuel.Tu@Sun.COM 		    &ixgbe_get_phy_firmware_version_tnx;
1419353SSamuel.Tu@Sun.COM 		break;
14210305SPaul.Guo@Sun.COM 	case ixgbe_phy_aq:
14310305SPaul.Guo@Sun.COM 		phy->ops.get_firmware_version =
14410998SChenlu.Chen@Sun.COM 		    &ixgbe_get_phy_firmware_version_generic;
14510305SPaul.Guo@Sun.COM 		break;
1469353SSamuel.Tu@Sun.COM 	default:
1479353SSamuel.Tu@Sun.COM 		break;
1489353SSamuel.Tu@Sun.COM 	}
1499353SSamuel.Tu@Sun.COM 
15010305SPaul.Guo@Sun.COM init_phy_ops_out:
1519353SSamuel.Tu@Sun.COM 	return (ret_val);
1529353SSamuel.Tu@Sun.COM }
1539353SSamuel.Tu@Sun.COM 
1549353SSamuel.Tu@Sun.COM s32
ixgbe_setup_sfp_modules_82599(struct ixgbe_hw * hw)1559353SSamuel.Tu@Sun.COM ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
1569353SSamuel.Tu@Sun.COM {
1579353SSamuel.Tu@Sun.COM 	s32 ret_val = IXGBE_SUCCESS;
1589353SSamuel.Tu@Sun.COM 	u16 list_offset, data_offset, data_value;
1599353SSamuel.Tu@Sun.COM 
1609353SSamuel.Tu@Sun.COM 	DEBUGFUNC("ixgbe_setup_sfp_modules_82599");
1619353SSamuel.Tu@Sun.COM 
1629353SSamuel.Tu@Sun.COM 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
1639353SSamuel.Tu@Sun.COM 		ixgbe_init_mac_link_ops_82599(hw);
1649353SSamuel.Tu@Sun.COM 
1659353SSamuel.Tu@Sun.COM 		hw->phy.ops.reset = NULL;
1669353SSamuel.Tu@Sun.COM 
1679353SSamuel.Tu@Sun.COM 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
1689353SSamuel.Tu@Sun.COM 		    &data_offset);
1699353SSamuel.Tu@Sun.COM 
1709353SSamuel.Tu@Sun.COM 		if (ret_val != IXGBE_SUCCESS)
1719353SSamuel.Tu@Sun.COM 			goto setup_sfp_out;
1729353SSamuel.Tu@Sun.COM 
17310305SPaul.Guo@Sun.COM 		/* PHY config will finish before releasing the semaphore */
17410305SPaul.Guo@Sun.COM 		ret_val = ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
17510305SPaul.Guo@Sun.COM 		if (ret_val != IXGBE_SUCCESS) {
17610305SPaul.Guo@Sun.COM 			ret_val = IXGBE_ERR_SWFW_SYNC;
17710305SPaul.Guo@Sun.COM 			goto setup_sfp_out;
17810305SPaul.Guo@Sun.COM 		}
17910305SPaul.Guo@Sun.COM 
1809353SSamuel.Tu@Sun.COM 		hw->eeprom.ops.read(hw, ++data_offset, &data_value);
1819353SSamuel.Tu@Sun.COM 		while (data_value != 0xffff) {
1829353SSamuel.Tu@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
1839353SSamuel.Tu@Sun.COM 			IXGBE_WRITE_FLUSH(hw);
1849353SSamuel.Tu@Sun.COM 			hw->eeprom.ops.read(hw, ++data_offset, &data_value);
1859353SSamuel.Tu@Sun.COM 		}
18610305SPaul.Guo@Sun.COM 		/* Now restart DSP by setting Restart_AN */
18710305SPaul.Guo@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
18810305SPaul.Guo@Sun.COM 		    (IXGBE_READ_REG(hw, IXGBE_AUTOC) | IXGBE_AUTOC_AN_RESTART));
18910305SPaul.Guo@Sun.COM 
19010305SPaul.Guo@Sun.COM 		/* Release the semaphore */
19110305SPaul.Guo@Sun.COM 		ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
19210305SPaul.Guo@Sun.COM 		/* Delay obtaining semaphore again to allow FW access */
19310305SPaul.Guo@Sun.COM 		msec_delay(hw->eeprom.semaphore_delay);
1949353SSamuel.Tu@Sun.COM 	}
1959353SSamuel.Tu@Sun.COM 
1969353SSamuel.Tu@Sun.COM setup_sfp_out:
1979353SSamuel.Tu@Sun.COM 	return (ret_val);
1989353SSamuel.Tu@Sun.COM }
1999353SSamuel.Tu@Sun.COM 
2009353SSamuel.Tu@Sun.COM /*
2019353SSamuel.Tu@Sun.COM  * ixgbe_init_ops_82599 - Inits func ptrs and MAC type
2029353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
2039353SSamuel.Tu@Sun.COM  *
2049353SSamuel.Tu@Sun.COM  * Initialize the function pointers and assign the MAC type for 82599.
2059353SSamuel.Tu@Sun.COM  * Does not touch the hardware.
2069353SSamuel.Tu@Sun.COM  */
2079353SSamuel.Tu@Sun.COM 
2089353SSamuel.Tu@Sun.COM s32
ixgbe_init_ops_82599(struct ixgbe_hw * hw)2099353SSamuel.Tu@Sun.COM ixgbe_init_ops_82599(struct ixgbe_hw *hw)
2109353SSamuel.Tu@Sun.COM {
2119353SSamuel.Tu@Sun.COM 	struct ixgbe_mac_info *mac = &hw->mac;
2129353SSamuel.Tu@Sun.COM 	struct ixgbe_phy_info *phy = &hw->phy;
2139353SSamuel.Tu@Sun.COM 	s32 ret_val;
2149353SSamuel.Tu@Sun.COM 
21510998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_init_ops_82599");
21610998SChenlu.Chen@Sun.COM 
2179353SSamuel.Tu@Sun.COM 	ret_val = ixgbe_init_phy_ops_generic(hw);
2189353SSamuel.Tu@Sun.COM 	ret_val = ixgbe_init_ops_generic(hw);
2199353SSamuel.Tu@Sun.COM 
2209353SSamuel.Tu@Sun.COM 	/* PHY */
2219353SSamuel.Tu@Sun.COM 	phy->ops.identify = &ixgbe_identify_phy_82599;
2229353SSamuel.Tu@Sun.COM 	phy->ops.init = &ixgbe_init_phy_ops_82599;
2239353SSamuel.Tu@Sun.COM 
2249353SSamuel.Tu@Sun.COM 	/* MAC */
2259353SSamuel.Tu@Sun.COM 	mac->ops.reset_hw = &ixgbe_reset_hw_82599;
226*13006SChenlu.Chen@Sun.COM 	mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_82599;
2279353SSamuel.Tu@Sun.COM 	mac->ops.get_media_type = &ixgbe_get_media_type_82599;
2289353SSamuel.Tu@Sun.COM 	mac->ops.get_supported_physical_layer =
2299353SSamuel.Tu@Sun.COM 	    &ixgbe_get_supported_physical_layer_82599;
2309353SSamuel.Tu@Sun.COM 	mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_82599;
2319353SSamuel.Tu@Sun.COM 	mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82599;
2329353SSamuel.Tu@Sun.COM 	mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82599;
2339353SSamuel.Tu@Sun.COM 	mac->ops.start_hw = &ixgbe_start_hw_rev_1_82599;
23412003SPaul.Guo@Sun.COM 	mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_82599;
23510998SChenlu.Chen@Sun.COM 	mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic;
23610998SChenlu.Chen@Sun.COM 	mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic;
2379353SSamuel.Tu@Sun.COM 	mac->ops.get_device_caps = &ixgbe_get_device_caps_82599;
23810998SChenlu.Chen@Sun.COM 	mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic;
239*13006SChenlu.Chen@Sun.COM 	mac->ops.get_fcoe_boot_status = &ixgbe_get_fcoe_boot_status_generic;
2409353SSamuel.Tu@Sun.COM 
2419353SSamuel.Tu@Sun.COM 	/* RAR, Multicast, VLAN */
24210998SChenlu.Chen@Sun.COM 	mac->ops.set_vmdq = &ixgbe_set_vmdq_generic;
24310998SChenlu.Chen@Sun.COM 	mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic;
24410998SChenlu.Chen@Sun.COM 	mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic;
2459353SSamuel.Tu@Sun.COM 	mac->rar_highwater = 1;
24610998SChenlu.Chen@Sun.COM 	mac->ops.set_vfta = &ixgbe_set_vfta_generic;
24710998SChenlu.Chen@Sun.COM 	mac->ops.clear_vfta = &ixgbe_clear_vfta_generic;
24810998SChenlu.Chen@Sun.COM 	mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic;
2499353SSamuel.Tu@Sun.COM 	mac->ops.setup_sfp = &ixgbe_setup_sfp_modules_82599;
2509353SSamuel.Tu@Sun.COM 
2519353SSamuel.Tu@Sun.COM 	/* Link */
2529353SSamuel.Tu@Sun.COM 	mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599;
25310998SChenlu.Chen@Sun.COM 	mac->ops.check_link = &ixgbe_check_mac_link_generic;
2549353SSamuel.Tu@Sun.COM 	ixgbe_init_mac_link_ops_82599(hw);
2559353SSamuel.Tu@Sun.COM 
2569353SSamuel.Tu@Sun.COM 	mac->mcft_size = 128;
2579353SSamuel.Tu@Sun.COM 	mac->vft_size = 128;
2589353SSamuel.Tu@Sun.COM 	mac->num_rar_entries = 128;
2599353SSamuel.Tu@Sun.COM 	mac->max_tx_queues = 128;
2609353SSamuel.Tu@Sun.COM 	mac->max_rx_queues = 128;
26110998SChenlu.Chen@Sun.COM 	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
2629353SSamuel.Tu@Sun.COM 
2639353SSamuel.Tu@Sun.COM 	return (ret_val);
2649353SSamuel.Tu@Sun.COM }
2659353SSamuel.Tu@Sun.COM 
2669353SSamuel.Tu@Sun.COM /*
2679353SSamuel.Tu@Sun.COM  * ixgbe_get_link_capabilities_82599 - Determines link capabilities
2689353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
2699353SSamuel.Tu@Sun.COM  * @speed: pointer to link speed
2709353SSamuel.Tu@Sun.COM  * @negotiation: true when autoneg or autotry is enabled
2719353SSamuel.Tu@Sun.COM  *
2729353SSamuel.Tu@Sun.COM  * Determines the link capabilities by reading the AUTOC register.
2739353SSamuel.Tu@Sun.COM  */
2749353SSamuel.Tu@Sun.COM s32
ixgbe_get_link_capabilities_82599(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * negotiation)2759353SSamuel.Tu@Sun.COM ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
2769353SSamuel.Tu@Sun.COM     ixgbe_link_speed *speed, bool *negotiation)
2779353SSamuel.Tu@Sun.COM {
2789353SSamuel.Tu@Sun.COM 	s32 status = IXGBE_SUCCESS;
2799353SSamuel.Tu@Sun.COM 	u32 autoc = 0;
2809353SSamuel.Tu@Sun.COM 
28110998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_get_link_capabilities_82599");
28210998SChenlu.Chen@Sun.COM 
283*13006SChenlu.Chen@Sun.COM 	/* Check if 1G SFP module. */
284*13006SChenlu.Chen@Sun.COM 	if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
285*13006SChenlu.Chen@Sun.COM 	    hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1) {
286*13006SChenlu.Chen@Sun.COM 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
287*13006SChenlu.Chen@Sun.COM 		*negotiation = true;
288*13006SChenlu.Chen@Sun.COM 		goto out;
289*13006SChenlu.Chen@Sun.COM 	}
290*13006SChenlu.Chen@Sun.COM 
2919353SSamuel.Tu@Sun.COM 	/*
2929353SSamuel.Tu@Sun.COM 	 * Determine link capabilities based on the stored value of AUTOC,
2939353SSamuel.Tu@Sun.COM 	 * which represents EEPROM defaults.  If AUTOC value has not
2949353SSamuel.Tu@Sun.COM 	 * been stored, use the current register values.
2959353SSamuel.Tu@Sun.COM 	 */
2969353SSamuel.Tu@Sun.COM 	if (hw->mac.orig_link_settings_stored)
2979353SSamuel.Tu@Sun.COM 		autoc = hw->mac.orig_autoc;
2989353SSamuel.Tu@Sun.COM 	else
2999353SSamuel.Tu@Sun.COM 		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
3009353SSamuel.Tu@Sun.COM 
3019353SSamuel.Tu@Sun.COM 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
3029353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
3039353SSamuel.Tu@Sun.COM 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
3049353SSamuel.Tu@Sun.COM 		*negotiation = false;
3059353SSamuel.Tu@Sun.COM 		break;
3069353SSamuel.Tu@Sun.COM 
3079353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
3089353SSamuel.Tu@Sun.COM 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
3099353SSamuel.Tu@Sun.COM 		*negotiation = false;
3109353SSamuel.Tu@Sun.COM 		break;
3119353SSamuel.Tu@Sun.COM 
3129353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_1G_AN:
3139353SSamuel.Tu@Sun.COM 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
3149353SSamuel.Tu@Sun.COM 		*negotiation = true;
3159353SSamuel.Tu@Sun.COM 		break;
3169353SSamuel.Tu@Sun.COM 
3179353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_10G_SERIAL:
3189353SSamuel.Tu@Sun.COM 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
3199353SSamuel.Tu@Sun.COM 		*negotiation = false;
3209353SSamuel.Tu@Sun.COM 		break;
3219353SSamuel.Tu@Sun.COM 
3229353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
3239353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
3249353SSamuel.Tu@Sun.COM 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
3259353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KR_SUPP)
3269353SSamuel.Tu@Sun.COM 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
3279353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
3289353SSamuel.Tu@Sun.COM 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
3299353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KX_SUPP)
3309353SSamuel.Tu@Sun.COM 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
3319353SSamuel.Tu@Sun.COM 		*negotiation = true;
3329353SSamuel.Tu@Sun.COM 		break;
3339353SSamuel.Tu@Sun.COM 
3349353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII:
3359353SSamuel.Tu@Sun.COM 		*speed = IXGBE_LINK_SPEED_100_FULL;
3369353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KR_SUPP)
3379353SSamuel.Tu@Sun.COM 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
3389353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
3399353SSamuel.Tu@Sun.COM 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
3409353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KX_SUPP)
3419353SSamuel.Tu@Sun.COM 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
3429353SSamuel.Tu@Sun.COM 		*negotiation = true;
3439353SSamuel.Tu@Sun.COM 		break;
3449353SSamuel.Tu@Sun.COM 
3459353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_SGMII_1G_100M:
3469353SSamuel.Tu@Sun.COM 		*speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL;
3479353SSamuel.Tu@Sun.COM 		*negotiation = false;
3489353SSamuel.Tu@Sun.COM 		break;
3499353SSamuel.Tu@Sun.COM 
3509353SSamuel.Tu@Sun.COM 	default:
3519353SSamuel.Tu@Sun.COM 		status = IXGBE_ERR_LINK_SETUP;
3529353SSamuel.Tu@Sun.COM 		goto out;
3539353SSamuel.Tu@Sun.COM 	}
3549353SSamuel.Tu@Sun.COM 
3559353SSamuel.Tu@Sun.COM 	if (hw->phy.multispeed_fiber) {
3569353SSamuel.Tu@Sun.COM 		*speed |= IXGBE_LINK_SPEED_10GB_FULL |
3579353SSamuel.Tu@Sun.COM 		    IXGBE_LINK_SPEED_1GB_FULL;
3589353SSamuel.Tu@Sun.COM 		*negotiation = true;
3599353SSamuel.Tu@Sun.COM 	}
3609353SSamuel.Tu@Sun.COM 
3619353SSamuel.Tu@Sun.COM out:
3629353SSamuel.Tu@Sun.COM 	return (status);
3639353SSamuel.Tu@Sun.COM }
3649353SSamuel.Tu@Sun.COM 
3659353SSamuel.Tu@Sun.COM /*
3669353SSamuel.Tu@Sun.COM  * ixgbe_get_media_type_82599 - Get media type
3679353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
3689353SSamuel.Tu@Sun.COM  *
3699353SSamuel.Tu@Sun.COM  * Returns the media type (fiber, copper, backplane)
3709353SSamuel.Tu@Sun.COM  */
3719353SSamuel.Tu@Sun.COM enum ixgbe_media_type
ixgbe_get_media_type_82599(struct ixgbe_hw * hw)3729353SSamuel.Tu@Sun.COM ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
3739353SSamuel.Tu@Sun.COM {
3749353SSamuel.Tu@Sun.COM 	enum ixgbe_media_type media_type;
3759353SSamuel.Tu@Sun.COM 
37610998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_get_media_type_82599");
37710998SChenlu.Chen@Sun.COM 
3789353SSamuel.Tu@Sun.COM 	/* Detect if there is a copper PHY attached. */
3799353SSamuel.Tu@Sun.COM 	if (hw->phy.type == ixgbe_phy_cu_unknown ||
38010305SPaul.Guo@Sun.COM 	    hw->phy.type == ixgbe_phy_tn ||
38110305SPaul.Guo@Sun.COM 	    hw->phy.type == ixgbe_phy_aq) {
3829353SSamuel.Tu@Sun.COM 		media_type = ixgbe_media_type_copper;
3839353SSamuel.Tu@Sun.COM 		goto out;
3849353SSamuel.Tu@Sun.COM 	}
3859353SSamuel.Tu@Sun.COM 
3869353SSamuel.Tu@Sun.COM 	switch (hw->device_id) {
3879353SSamuel.Tu@Sun.COM 	case IXGBE_DEV_ID_82599_KX4:
38810998SChenlu.Chen@Sun.COM 	case IXGBE_DEV_ID_82599_KX4_MEZZ:
38910998SChenlu.Chen@Sun.COM 	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
39012003SPaul.Guo@Sun.COM 	case IXGBE_DEV_ID_82599_KR:
39110305SPaul.Guo@Sun.COM 	case IXGBE_DEV_ID_82599_XAUI_LOM:
3929353SSamuel.Tu@Sun.COM 		/* Default device ID is mezzanine card KX/KX4 */
3939353SSamuel.Tu@Sun.COM 		media_type = ixgbe_media_type_backplane;
3949353SSamuel.Tu@Sun.COM 		break;
3959353SSamuel.Tu@Sun.COM 	case IXGBE_DEV_ID_82599_SFP:
39610998SChenlu.Chen@Sun.COM 	case IXGBE_DEV_ID_82599_SFP_EM:
3979353SSamuel.Tu@Sun.COM 		media_type = ixgbe_media_type_fiber;
3989353SSamuel.Tu@Sun.COM 		break;
3999353SSamuel.Tu@Sun.COM 	case IXGBE_DEV_ID_82599_CX4:
40010998SChenlu.Chen@Sun.COM 		media_type = ixgbe_media_type_cx4;
4019353SSamuel.Tu@Sun.COM 		break;
402*13006SChenlu.Chen@Sun.COM 	case IXGBE_DEV_ID_82599_T3_LOM:
40312003SPaul.Guo@Sun.COM 		media_type = ixgbe_media_type_copper;
40412003SPaul.Guo@Sun.COM 		break;
4059353SSamuel.Tu@Sun.COM 	default:
4069353SSamuel.Tu@Sun.COM 		media_type = ixgbe_media_type_unknown;
4079353SSamuel.Tu@Sun.COM 		break;
4089353SSamuel.Tu@Sun.COM 	}
4099353SSamuel.Tu@Sun.COM out:
4109353SSamuel.Tu@Sun.COM 	return (media_type);
4119353SSamuel.Tu@Sun.COM }
4129353SSamuel.Tu@Sun.COM 
4139353SSamuel.Tu@Sun.COM /*
41410998SChenlu.Chen@Sun.COM  * ixgbe_start_mac_link_82599 - Setup MAC link settings
4159353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
4169353SSamuel.Tu@Sun.COM  *
4179353SSamuel.Tu@Sun.COM  * Configures link settings based on values in the ixgbe_hw struct.
4189353SSamuel.Tu@Sun.COM  * Restarts the link.  Performs autonegotiation if needed.
4199353SSamuel.Tu@Sun.COM  */
4209353SSamuel.Tu@Sun.COM s32
ixgbe_start_mac_link_82599(struct ixgbe_hw * hw,bool autoneg_wait_to_complete)42110998SChenlu.Chen@Sun.COM ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, bool autoneg_wait_to_complete)
4229353SSamuel.Tu@Sun.COM {
4239353SSamuel.Tu@Sun.COM 	u32 autoc_reg;
4249353SSamuel.Tu@Sun.COM 	u32 links_reg;
4259353SSamuel.Tu@Sun.COM 	u32 i;
4269353SSamuel.Tu@Sun.COM 	s32 status = IXGBE_SUCCESS;
4279353SSamuel.Tu@Sun.COM 
42810998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_start_mac_link_82599");
42910998SChenlu.Chen@Sun.COM 
4309353SSamuel.Tu@Sun.COM 	/* Restart link */
4319353SSamuel.Tu@Sun.COM 	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
4329353SSamuel.Tu@Sun.COM 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
4339353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
4349353SSamuel.Tu@Sun.COM 
4359353SSamuel.Tu@Sun.COM 	/* Only poll for autoneg to complete if specified to do so */
43610998SChenlu.Chen@Sun.COM 	if (autoneg_wait_to_complete) {
4379353SSamuel.Tu@Sun.COM 		if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
4389353SSamuel.Tu@Sun.COM 		    IXGBE_AUTOC_LMS_KX4_KX_KR ||
4399353SSamuel.Tu@Sun.COM 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
4409353SSamuel.Tu@Sun.COM 		    IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
4419353SSamuel.Tu@Sun.COM 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
4429353SSamuel.Tu@Sun.COM 		    IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
4439353SSamuel.Tu@Sun.COM 			links_reg = 0; /* Just in case Autoneg time = 0 */
4449353SSamuel.Tu@Sun.COM 			for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
4459353SSamuel.Tu@Sun.COM 				links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
4469353SSamuel.Tu@Sun.COM 				if (links_reg & IXGBE_LINKS_KX_AN_COMP)
4479353SSamuel.Tu@Sun.COM 					break;
4489353SSamuel.Tu@Sun.COM 				msec_delay(100);
4499353SSamuel.Tu@Sun.COM 			}
4509353SSamuel.Tu@Sun.COM 			if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
4519353SSamuel.Tu@Sun.COM 				status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
4529353SSamuel.Tu@Sun.COM 				DEBUGOUT("Autoneg did not complete.\n");
4539353SSamuel.Tu@Sun.COM 			}
4549353SSamuel.Tu@Sun.COM 		}
4559353SSamuel.Tu@Sun.COM 	}
4569353SSamuel.Tu@Sun.COM 
4579353SSamuel.Tu@Sun.COM 	/* Add delay to filter out noises during initial link setup */
4589353SSamuel.Tu@Sun.COM 	msec_delay(50);
4599353SSamuel.Tu@Sun.COM 
4609353SSamuel.Tu@Sun.COM 	return (status);
4619353SSamuel.Tu@Sun.COM }
4629353SSamuel.Tu@Sun.COM 
4639353SSamuel.Tu@Sun.COM /*
464*13006SChenlu.Chen@Sun.COM  * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
465*13006SChenlu.Chen@Sun.COM  * @hw: pointer to hardware structure
466*13006SChenlu.Chen@Sun.COM  *
467*13006SChenlu.Chen@Sun.COM  * The base drivers may require better control over SFP+ module
468*13006SChenlu.Chen@Sun.COM  * PHY states.  This includes selectively shutting down the Tx
469*13006SChenlu.Chen@Sun.COM  * laser on the PHY, effectively halting physical link.
470*13006SChenlu.Chen@Sun.COM  */
471*13006SChenlu.Chen@Sun.COM void
ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)472*13006SChenlu.Chen@Sun.COM ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
473*13006SChenlu.Chen@Sun.COM {
474*13006SChenlu.Chen@Sun.COM 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
475*13006SChenlu.Chen@Sun.COM 
476*13006SChenlu.Chen@Sun.COM 	/*
477*13006SChenlu.Chen@Sun.COM 	 * Disable tx laser; allow 100us to go dark per spec
478*13006SChenlu.Chen@Sun.COM 	 */
479*13006SChenlu.Chen@Sun.COM 	esdp_reg |= IXGBE_ESDP_SDP3;
480*13006SChenlu.Chen@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
481*13006SChenlu.Chen@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
482*13006SChenlu.Chen@Sun.COM 	usec_delay(100);
483*13006SChenlu.Chen@Sun.COM }
484*13006SChenlu.Chen@Sun.COM 
485*13006SChenlu.Chen@Sun.COM /*
486*13006SChenlu.Chen@Sun.COM  * ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser
487*13006SChenlu.Chen@Sun.COM  * @hw: pointer to hardware structure
488*13006SChenlu.Chen@Sun.COM  *
489*13006SChenlu.Chen@Sun.COM  * The base drivers may require better control over SFP+ module
490*13006SChenlu.Chen@Sun.COM  * PHY states.  This includes selectively turning on the Tx
491*13006SChenlu.Chen@Sun.COM  * laser on the PHY, effectively starting physical link.
492*13006SChenlu.Chen@Sun.COM  */
493*13006SChenlu.Chen@Sun.COM void
ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)494*13006SChenlu.Chen@Sun.COM ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
495*13006SChenlu.Chen@Sun.COM {
496*13006SChenlu.Chen@Sun.COM 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
497*13006SChenlu.Chen@Sun.COM 
498*13006SChenlu.Chen@Sun.COM 	/*
499*13006SChenlu.Chen@Sun.COM 	 * Enable tx laser; allow 100ms to light up
500*13006SChenlu.Chen@Sun.COM 	 */
501*13006SChenlu.Chen@Sun.COM 	esdp_reg &= ~IXGBE_ESDP_SDP3;
502*13006SChenlu.Chen@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
503*13006SChenlu.Chen@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
504*13006SChenlu.Chen@Sun.COM 	msec_delay(100);
505*13006SChenlu.Chen@Sun.COM }
506*13006SChenlu.Chen@Sun.COM 
507*13006SChenlu.Chen@Sun.COM /*
508*13006SChenlu.Chen@Sun.COM  * ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
509*13006SChenlu.Chen@Sun.COM  * @hw: pointer to hardware structure
510*13006SChenlu.Chen@Sun.COM  *
511*13006SChenlu.Chen@Sun.COM  * When the driver changes the link speeds that it can support,
512*13006SChenlu.Chen@Sun.COM  * it sets autotry_restart to true to indicate that we need to
513*13006SChenlu.Chen@Sun.COM  * initiate a new autotry session with the link partner.  To do
514*13006SChenlu.Chen@Sun.COM  * so, we set the speed then disable and re-enable the tx laser, to
515*13006SChenlu.Chen@Sun.COM  * alert the link partner that it also needs to restart autotry on its
516*13006SChenlu.Chen@Sun.COM  * end.  This is consistent with true clause 37 autoneg, which also
517*13006SChenlu.Chen@Sun.COM  * involves a loss of signal.
518*13006SChenlu.Chen@Sun.COM  */
519*13006SChenlu.Chen@Sun.COM void
ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw * hw)520*13006SChenlu.Chen@Sun.COM ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
521*13006SChenlu.Chen@Sun.COM {
522*13006SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber");
523*13006SChenlu.Chen@Sun.COM 
524*13006SChenlu.Chen@Sun.COM 	if (hw->mac.autotry_restart) {
525*13006SChenlu.Chen@Sun.COM 		ixgbe_disable_tx_laser_multispeed_fiber(hw);
526*13006SChenlu.Chen@Sun.COM 		ixgbe_enable_tx_laser_multispeed_fiber(hw);
527*13006SChenlu.Chen@Sun.COM 		hw->mac.autotry_restart = false;
528*13006SChenlu.Chen@Sun.COM 	}
529*13006SChenlu.Chen@Sun.COM }
530*13006SChenlu.Chen@Sun.COM 
531*13006SChenlu.Chen@Sun.COM /*
53210998SChenlu.Chen@Sun.COM  * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
5339353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
5349353SSamuel.Tu@Sun.COM  * @speed: new link speed
5359353SSamuel.Tu@Sun.COM  * @autoneg: true if autonegotiation enabled
5369353SSamuel.Tu@Sun.COM  * @autoneg_wait_to_complete: true when waiting for completion is needed
5379353SSamuel.Tu@Sun.COM  *
5389353SSamuel.Tu@Sun.COM  * Set the link speed in the AUTOC register and restarts link.
5399353SSamuel.Tu@Sun.COM  */
5409353SSamuel.Tu@Sun.COM s32
ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg,bool autoneg_wait_to_complete)54110998SChenlu.Chen@Sun.COM ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
5429353SSamuel.Tu@Sun.COM     ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete)
5439353SSamuel.Tu@Sun.COM {
5449353SSamuel.Tu@Sun.COM 	s32 status = IXGBE_SUCCESS;
5459353SSamuel.Tu@Sun.COM 	ixgbe_link_speed link_speed;
5469353SSamuel.Tu@Sun.COM 	ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
5479353SSamuel.Tu@Sun.COM 	u32 speedcnt = 0;
5489353SSamuel.Tu@Sun.COM 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
54910305SPaul.Guo@Sun.COM 	u32 i = 0;
5509353SSamuel.Tu@Sun.COM 	bool link_up = false;
5519353SSamuel.Tu@Sun.COM 	bool negotiation;
5529353SSamuel.Tu@Sun.COM 
55310998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber");
55410998SChenlu.Chen@Sun.COM 
5559353SSamuel.Tu@Sun.COM 	/* Mask off requested but non-supported speeds */
5569353SSamuel.Tu@Sun.COM 	status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation);
5579353SSamuel.Tu@Sun.COM 	if (status != IXGBE_SUCCESS)
55810998SChenlu.Chen@Sun.COM 		return (status);
5599353SSamuel.Tu@Sun.COM 
5609353SSamuel.Tu@Sun.COM 	speed &= link_speed;
5619353SSamuel.Tu@Sun.COM 
56210305SPaul.Guo@Sun.COM 	/*
5639353SSamuel.Tu@Sun.COM 	 * Try each speed one by one, highest priority first.  We do this in
5649353SSamuel.Tu@Sun.COM 	 * software because 10gb fiber doesn't support speed autonegotiation.
5659353SSamuel.Tu@Sun.COM 	 */
5669353SSamuel.Tu@Sun.COM 	if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
5679353SSamuel.Tu@Sun.COM 		speedcnt++;
5689353SSamuel.Tu@Sun.COM 		highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
5699353SSamuel.Tu@Sun.COM 
5709353SSamuel.Tu@Sun.COM 		/* If we already have link at this speed, just jump out */
5719353SSamuel.Tu@Sun.COM 		status = ixgbe_check_link(hw, &link_speed, &link_up, false);
5729353SSamuel.Tu@Sun.COM 		if (status != IXGBE_SUCCESS)
57310998SChenlu.Chen@Sun.COM 			return (status);
5749353SSamuel.Tu@Sun.COM 
5759353SSamuel.Tu@Sun.COM 		if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
5769353SSamuel.Tu@Sun.COM 			goto out;
5779353SSamuel.Tu@Sun.COM 
57810305SPaul.Guo@Sun.COM 		/* Set the module link speed */
5799353SSamuel.Tu@Sun.COM 		esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
5809353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
581*13006SChenlu.Chen@Sun.COM 		IXGBE_WRITE_FLUSH(hw);
5829353SSamuel.Tu@Sun.COM 
5839353SSamuel.Tu@Sun.COM 		/* Allow module to change analog characteristics (1G->10G) */
5849353SSamuel.Tu@Sun.COM 		msec_delay(40);
5859353SSamuel.Tu@Sun.COM 
58610998SChenlu.Chen@Sun.COM 		status = ixgbe_setup_mac_link_82599(
5879353SSamuel.Tu@Sun.COM 		    hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg,
5889353SSamuel.Tu@Sun.COM 		    autoneg_wait_to_complete);
5899353SSamuel.Tu@Sun.COM 		if (status != IXGBE_SUCCESS)
59010998SChenlu.Chen@Sun.COM 			return (status);
5919353SSamuel.Tu@Sun.COM 
59210305SPaul.Guo@Sun.COM 		/* Flap the tx laser if it has not already been done */
593*13006SChenlu.Chen@Sun.COM 		ixgbe_flap_tx_laser(hw);
5949353SSamuel.Tu@Sun.COM 
59510998SChenlu.Chen@Sun.COM 		/*
59610998SChenlu.Chen@Sun.COM 		 * Wait for the controller to acquire link.  Per IEEE 802.3ap,
59710998SChenlu.Chen@Sun.COM 		 * Section 73.10.2, we may have to wait up to 500ms if KR is
59810998SChenlu.Chen@Sun.COM 		 * attempted.  82599 uses the same timing for 10g SFI.
59910998SChenlu.Chen@Sun.COM 		 */
60010305SPaul.Guo@Sun.COM 		for (i = 0; i < 5; i++) {
60110305SPaul.Guo@Sun.COM 			/* Wait for the link partner to also set speed */
60210305SPaul.Guo@Sun.COM 			msec_delay(100);
6039353SSamuel.Tu@Sun.COM 
60410305SPaul.Guo@Sun.COM 			/* If we have link, just jump out */
60510305SPaul.Guo@Sun.COM 			status = ixgbe_check_link(hw, &link_speed,
60610305SPaul.Guo@Sun.COM 			    &link_up, false);
60710305SPaul.Guo@Sun.COM 			if (status != IXGBE_SUCCESS)
60810998SChenlu.Chen@Sun.COM 				return (status);
60910305SPaul.Guo@Sun.COM 
61010305SPaul.Guo@Sun.COM 			if (link_up)
61110305SPaul.Guo@Sun.COM 				goto out;
61210305SPaul.Guo@Sun.COM 		}
6139353SSamuel.Tu@Sun.COM 	}
6149353SSamuel.Tu@Sun.COM 
6159353SSamuel.Tu@Sun.COM 	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
6169353SSamuel.Tu@Sun.COM 		speedcnt++;
6179353SSamuel.Tu@Sun.COM 		if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
6189353SSamuel.Tu@Sun.COM 			highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
6199353SSamuel.Tu@Sun.COM 
6209353SSamuel.Tu@Sun.COM 		/* If we already have link at this speed, just jump out */
6219353SSamuel.Tu@Sun.COM 		status = ixgbe_check_link(hw, &link_speed, &link_up, false);
6229353SSamuel.Tu@Sun.COM 		if (status != IXGBE_SUCCESS)
62310998SChenlu.Chen@Sun.COM 			return (status);
6249353SSamuel.Tu@Sun.COM 
6259353SSamuel.Tu@Sun.COM 		if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
6269353SSamuel.Tu@Sun.COM 			goto out;
6279353SSamuel.Tu@Sun.COM 
62810305SPaul.Guo@Sun.COM 		/* Set the module link speed */
6299353SSamuel.Tu@Sun.COM 		esdp_reg &= ~IXGBE_ESDP_SDP5;
6309353SSamuel.Tu@Sun.COM 		esdp_reg |= IXGBE_ESDP_SDP5_DIR;
6319353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
632*13006SChenlu.Chen@Sun.COM 		IXGBE_WRITE_FLUSH(hw);
6339353SSamuel.Tu@Sun.COM 
6349353SSamuel.Tu@Sun.COM 		/* Allow module to change analog characteristics (10G->1G) */
6359353SSamuel.Tu@Sun.COM 		msec_delay(40);
6369353SSamuel.Tu@Sun.COM 
63710998SChenlu.Chen@Sun.COM 		status = ixgbe_setup_mac_link_82599(
6389353SSamuel.Tu@Sun.COM 		    hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg,
6399353SSamuel.Tu@Sun.COM 		    autoneg_wait_to_complete);
6409353SSamuel.Tu@Sun.COM 		if (status != IXGBE_SUCCESS)
64110998SChenlu.Chen@Sun.COM 			return (status);
6429353SSamuel.Tu@Sun.COM 
64310305SPaul.Guo@Sun.COM 		/* Flap the tx laser if it has not already been done */
644*13006SChenlu.Chen@Sun.COM 		ixgbe_flap_tx_laser(hw);
64510305SPaul.Guo@Sun.COM 
64610305SPaul.Guo@Sun.COM 		/* Wait for the link partner to also set speed */
6479353SSamuel.Tu@Sun.COM 		msec_delay(100);
6489353SSamuel.Tu@Sun.COM 
6499353SSamuel.Tu@Sun.COM 		/* If we have link, just jump out */
6509353SSamuel.Tu@Sun.COM 		status = ixgbe_check_link(hw, &link_speed, &link_up, false);
6519353SSamuel.Tu@Sun.COM 		if (status != IXGBE_SUCCESS)
65210998SChenlu.Chen@Sun.COM 			return (status);
6539353SSamuel.Tu@Sun.COM 
6549353SSamuel.Tu@Sun.COM 		if (link_up)
6559353SSamuel.Tu@Sun.COM 			goto out;
6569353SSamuel.Tu@Sun.COM 	}
6579353SSamuel.Tu@Sun.COM 
6589353SSamuel.Tu@Sun.COM 	/*
6599353SSamuel.Tu@Sun.COM 	 * We didn't get link.  Configure back to the highest speed we tried,
6609353SSamuel.Tu@Sun.COM 	 * (if there was more than one).  We call ourselves back with just the
6619353SSamuel.Tu@Sun.COM 	 * single highest speed that the user requested.
6629353SSamuel.Tu@Sun.COM 	 */
6639353SSamuel.Tu@Sun.COM 	if (speedcnt > 1)
66410998SChenlu.Chen@Sun.COM 		status = ixgbe_setup_mac_link_multispeed_fiber(hw,
6659353SSamuel.Tu@Sun.COM 		    highest_link_speed, autoneg, autoneg_wait_to_complete);
6669353SSamuel.Tu@Sun.COM 
6679353SSamuel.Tu@Sun.COM out:
66810998SChenlu.Chen@Sun.COM 	/* Set autoneg_advertised value based on input link speed */
66910998SChenlu.Chen@Sun.COM 	hw->phy.autoneg_advertised = 0;
67010998SChenlu.Chen@Sun.COM 
67110998SChenlu.Chen@Sun.COM 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
67210998SChenlu.Chen@Sun.COM 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
67310998SChenlu.Chen@Sun.COM 
67410998SChenlu.Chen@Sun.COM 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
67510998SChenlu.Chen@Sun.COM 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
67610998SChenlu.Chen@Sun.COM 
67710998SChenlu.Chen@Sun.COM 	return (status);
67810998SChenlu.Chen@Sun.COM }
67910998SChenlu.Chen@Sun.COM 
68010998SChenlu.Chen@Sun.COM /*
68110998SChenlu.Chen@Sun.COM  * ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed
68210998SChenlu.Chen@Sun.COM  * @hw: pointer to hardware structure
68310998SChenlu.Chen@Sun.COM  * @speed: new link speed
68410998SChenlu.Chen@Sun.COM  * @autoneg: true if autonegotiation enabled
68510998SChenlu.Chen@Sun.COM  * @autoneg_wait_to_complete: true when waiting for completion is needed
68610998SChenlu.Chen@Sun.COM  *
68710998SChenlu.Chen@Sun.COM  * Implements the Intel SmartSpeed algorithm.
68810998SChenlu.Chen@Sun.COM  */
68910998SChenlu.Chen@Sun.COM s32
ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg,bool autoneg_wait_to_complete)69010998SChenlu.Chen@Sun.COM ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
69110998SChenlu.Chen@Sun.COM     ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete)
69210998SChenlu.Chen@Sun.COM {
69310998SChenlu.Chen@Sun.COM 	s32 status = IXGBE_SUCCESS;
694*13006SChenlu.Chen@Sun.COM 	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
69510998SChenlu.Chen@Sun.COM 	s32 i, j;
69610998SChenlu.Chen@Sun.COM 	bool link_up = false;
69710998SChenlu.Chen@Sun.COM 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
69810998SChenlu.Chen@Sun.COM 
69910998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_setup_mac_link_smartspeed");
70010998SChenlu.Chen@Sun.COM 
70110998SChenlu.Chen@Sun.COM 	/* Set autoneg_advertised value based on input link speed */
70210998SChenlu.Chen@Sun.COM 	hw->phy.autoneg_advertised = 0;
70310998SChenlu.Chen@Sun.COM 
70410998SChenlu.Chen@Sun.COM 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
70510998SChenlu.Chen@Sun.COM 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
70610998SChenlu.Chen@Sun.COM 
70710998SChenlu.Chen@Sun.COM 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
70810998SChenlu.Chen@Sun.COM 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
70910998SChenlu.Chen@Sun.COM 
71010998SChenlu.Chen@Sun.COM 	if (speed & IXGBE_LINK_SPEED_100_FULL)
71110998SChenlu.Chen@Sun.COM 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
71210998SChenlu.Chen@Sun.COM 
71310998SChenlu.Chen@Sun.COM 	/*
71410998SChenlu.Chen@Sun.COM 	 * Implement Intel SmartSpeed algorithm.  SmartSpeed will reduce the
71510998SChenlu.Chen@Sun.COM 	 * autoneg advertisement if link is unable to be established at the
71610998SChenlu.Chen@Sun.COM 	 * highest negotiated rate.  This can sometimes happen due to integrity
71710998SChenlu.Chen@Sun.COM 	 * issues with the physical media connection.
71810998SChenlu.Chen@Sun.COM 	 */
71910998SChenlu.Chen@Sun.COM 
72010998SChenlu.Chen@Sun.COM 	/* First, try to get link with full advertisement */
72110998SChenlu.Chen@Sun.COM 	hw->phy.smart_speed_active = false;
72210998SChenlu.Chen@Sun.COM 	for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) {
72310998SChenlu.Chen@Sun.COM 		status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
72410998SChenlu.Chen@Sun.COM 		    autoneg_wait_to_complete);
72510998SChenlu.Chen@Sun.COM 		if (status != IXGBE_SUCCESS)
72610998SChenlu.Chen@Sun.COM 			goto out;
72710998SChenlu.Chen@Sun.COM 
72810998SChenlu.Chen@Sun.COM 		/*
72910998SChenlu.Chen@Sun.COM 		 * Wait for the controller to acquire link.  Per IEEE 802.3ap,
73010998SChenlu.Chen@Sun.COM 		 * Section 73.10.2, we may have to wait up to 500ms if KR is
73110998SChenlu.Chen@Sun.COM 		 * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per
73210998SChenlu.Chen@Sun.COM 		 * Table 9 in the AN MAS.
73310998SChenlu.Chen@Sun.COM 		 */
73410998SChenlu.Chen@Sun.COM 		for (i = 0; i < 5; i++) {
73510998SChenlu.Chen@Sun.COM 			msec_delay(100);
73610998SChenlu.Chen@Sun.COM 
73710998SChenlu.Chen@Sun.COM 			/* If we have link, just jump out */
73810998SChenlu.Chen@Sun.COM 			status = ixgbe_check_link(hw, &link_speed, &link_up,
73910998SChenlu.Chen@Sun.COM 			    false);
74010998SChenlu.Chen@Sun.COM 			if (status != IXGBE_SUCCESS)
74110998SChenlu.Chen@Sun.COM 				goto out;
74210998SChenlu.Chen@Sun.COM 
74310998SChenlu.Chen@Sun.COM 			if (link_up)
74410998SChenlu.Chen@Sun.COM 				goto out;
74510998SChenlu.Chen@Sun.COM 		}
74610998SChenlu.Chen@Sun.COM 	}
74710998SChenlu.Chen@Sun.COM 
74810998SChenlu.Chen@Sun.COM 	/*
74910998SChenlu.Chen@Sun.COM 	 * We didn't get link.  If we advertised KR plus one of KX4/KX
75010998SChenlu.Chen@Sun.COM 	 * (or BX4/BX), then disable KR and try again.
75110998SChenlu.Chen@Sun.COM 	 */
75210998SChenlu.Chen@Sun.COM 	if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) ||
75310998SChenlu.Chen@Sun.COM 	    ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0))
75410998SChenlu.Chen@Sun.COM 		goto out;
75510998SChenlu.Chen@Sun.COM 
75610998SChenlu.Chen@Sun.COM 	/* Turn SmartSpeed on to disable KR support */
75710998SChenlu.Chen@Sun.COM 	hw->phy.smart_speed_active = true;
75810998SChenlu.Chen@Sun.COM 	status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
75910998SChenlu.Chen@Sun.COM 	    autoneg_wait_to_complete);
76010998SChenlu.Chen@Sun.COM 	if (status != IXGBE_SUCCESS)
76110998SChenlu.Chen@Sun.COM 		goto out;
76210998SChenlu.Chen@Sun.COM 
76310998SChenlu.Chen@Sun.COM 	/*
76410998SChenlu.Chen@Sun.COM 	 * Wait for the controller to acquire link.  600ms will allow for
76510998SChenlu.Chen@Sun.COM 	 * the AN link_fail_inhibit_timer as well for multiple cycles of
76610998SChenlu.Chen@Sun.COM 	 * parallel detect, both 10g and 1g. This allows for the maximum
76710998SChenlu.Chen@Sun.COM 	 * connect attempts as defined in the AN MAS table 73-7.
76810998SChenlu.Chen@Sun.COM 	 */
76910998SChenlu.Chen@Sun.COM 	for (i = 0; i < 6; i++) {
77010998SChenlu.Chen@Sun.COM 		msec_delay(100);
77110998SChenlu.Chen@Sun.COM 
77210998SChenlu.Chen@Sun.COM 		/* If we have link, just jump out */
77310998SChenlu.Chen@Sun.COM 		status = ixgbe_check_link(hw, &link_speed, &link_up, false);
77410998SChenlu.Chen@Sun.COM 		if (status != IXGBE_SUCCESS)
77510998SChenlu.Chen@Sun.COM 			goto out;
77610998SChenlu.Chen@Sun.COM 
77710998SChenlu.Chen@Sun.COM 		if (link_up)
77810998SChenlu.Chen@Sun.COM 			goto out;
77910998SChenlu.Chen@Sun.COM 	}
78010998SChenlu.Chen@Sun.COM 
78110998SChenlu.Chen@Sun.COM 	/* We didn't get link.  Turn SmartSpeed back off. */
78210998SChenlu.Chen@Sun.COM 	hw->phy.smart_speed_active = false;
78310998SChenlu.Chen@Sun.COM 	status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
78410998SChenlu.Chen@Sun.COM 	    autoneg_wait_to_complete);
78510998SChenlu.Chen@Sun.COM 
78610998SChenlu.Chen@Sun.COM out:
787*13006SChenlu.Chen@Sun.COM 	if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
788*13006SChenlu.Chen@Sun.COM 		DEBUGOUT("Smartspeed has downgraded the link speed "
789*13006SChenlu.Chen@Sun.COM 		"from the maximum advertised\n");
7909353SSamuel.Tu@Sun.COM 	return (status);
7919353SSamuel.Tu@Sun.COM }
7929353SSamuel.Tu@Sun.COM 
7939353SSamuel.Tu@Sun.COM /*
79410998SChenlu.Chen@Sun.COM  * ixgbe_setup_mac_link_82599 - Set MAC link speed
7959353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
7969353SSamuel.Tu@Sun.COM  * @speed: new link speed
7979353SSamuel.Tu@Sun.COM  * @autoneg: true if autonegotiation enabled
7989353SSamuel.Tu@Sun.COM  * @autoneg_wait_to_complete: true when waiting for completion is needed
7999353SSamuel.Tu@Sun.COM  *
8009353SSamuel.Tu@Sun.COM  * Set the link speed in the AUTOC register and restarts link.
8019353SSamuel.Tu@Sun.COM  */
8029353SSamuel.Tu@Sun.COM s32
ixgbe_setup_mac_link_82599(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg,bool autoneg_wait_to_complete)80310998SChenlu.Chen@Sun.COM ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
8049353SSamuel.Tu@Sun.COM     ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete)
8059353SSamuel.Tu@Sun.COM {
8069353SSamuel.Tu@Sun.COM 	s32 status = IXGBE_SUCCESS;
8079353SSamuel.Tu@Sun.COM 	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
8089353SSamuel.Tu@Sun.COM 	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
80910305SPaul.Guo@Sun.COM 	u32 start_autoc = autoc;
81010305SPaul.Guo@Sun.COM 	u32 orig_autoc = 0;
8119353SSamuel.Tu@Sun.COM 	u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
8129353SSamuel.Tu@Sun.COM 	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
8139353SSamuel.Tu@Sun.COM 	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
8149353SSamuel.Tu@Sun.COM 	u32 links_reg;
8159353SSamuel.Tu@Sun.COM 	u32 i;
8169353SSamuel.Tu@Sun.COM 	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
8179353SSamuel.Tu@Sun.COM 
81810998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_setup_mac_link_82599");
81910998SChenlu.Chen@Sun.COM 
8209353SSamuel.Tu@Sun.COM 	/* Check to see if speed passed in is supported. */
8219353SSamuel.Tu@Sun.COM 	status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg);
8229353SSamuel.Tu@Sun.COM 	if (status != IXGBE_SUCCESS)
8239353SSamuel.Tu@Sun.COM 		goto out;
8249353SSamuel.Tu@Sun.COM 
8259353SSamuel.Tu@Sun.COM 	speed &= link_capabilities;
8269353SSamuel.Tu@Sun.COM 
8279353SSamuel.Tu@Sun.COM 	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
8289353SSamuel.Tu@Sun.COM 		status = IXGBE_ERR_LINK_SETUP;
82910305SPaul.Guo@Sun.COM 		goto out;
83010305SPaul.Guo@Sun.COM 	}
83110305SPaul.Guo@Sun.COM 
83210305SPaul.Guo@Sun.COM 	/*
83310305SPaul.Guo@Sun.COM 	 * Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support
83410305SPaul.Guo@Sun.COM 	 */
83510305SPaul.Guo@Sun.COM 	if (hw->mac.orig_link_settings_stored)
83610305SPaul.Guo@Sun.COM 		orig_autoc = hw->mac.orig_autoc;
83710305SPaul.Guo@Sun.COM 	else
83810305SPaul.Guo@Sun.COM 		orig_autoc = autoc;
83910305SPaul.Guo@Sun.COM 
84010305SPaul.Guo@Sun.COM 	if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
8419353SSamuel.Tu@Sun.COM 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
8429353SSamuel.Tu@Sun.COM 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
8439353SSamuel.Tu@Sun.COM 		/* Set KX4/KX/KR support according to speed requested */
8449353SSamuel.Tu@Sun.COM 		autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP);
8459353SSamuel.Tu@Sun.COM 		if (speed & IXGBE_LINK_SPEED_10GB_FULL)
84610305SPaul.Guo@Sun.COM 			if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)
8479353SSamuel.Tu@Sun.COM 				autoc |= IXGBE_AUTOC_KX4_SUPP;
84810998SChenlu.Chen@Sun.COM 			if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) &&
84910998SChenlu.Chen@Sun.COM 			    (hw->phy.smart_speed_active == false))
8509353SSamuel.Tu@Sun.COM 				autoc |= IXGBE_AUTOC_KR_SUPP;
8519353SSamuel.Tu@Sun.COM 		if (speed & IXGBE_LINK_SPEED_1GB_FULL)
8529353SSamuel.Tu@Sun.COM 			autoc |= IXGBE_AUTOC_KX_SUPP;
8539353SSamuel.Tu@Sun.COM 	} else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) &&
8549353SSamuel.Tu@Sun.COM 	    (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN ||
8559353SSamuel.Tu@Sun.COM 	    link_mode == IXGBE_AUTOC_LMS_1G_AN)) {
8569353SSamuel.Tu@Sun.COM 		/* Switch from 1G SFI to 10G SFI if requested */
8579353SSamuel.Tu@Sun.COM 		if ((speed == IXGBE_LINK_SPEED_10GB_FULL) &&
8589353SSamuel.Tu@Sun.COM 		    (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) {
8599353SSamuel.Tu@Sun.COM 			autoc &= ~IXGBE_AUTOC_LMS_MASK;
8609353SSamuel.Tu@Sun.COM 			autoc |= IXGBE_AUTOC_LMS_10G_SERIAL;
8619353SSamuel.Tu@Sun.COM 		}
8629353SSamuel.Tu@Sun.COM 	} else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) &&
8639353SSamuel.Tu@Sun.COM 	    (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) {
8649353SSamuel.Tu@Sun.COM 		/* Switch from 10G SFI to 1G SFI if requested */
8659353SSamuel.Tu@Sun.COM 		if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
8669353SSamuel.Tu@Sun.COM 		    (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) {
8679353SSamuel.Tu@Sun.COM 			autoc &= ~IXGBE_AUTOC_LMS_MASK;
8689353SSamuel.Tu@Sun.COM 			if (autoneg)
8699353SSamuel.Tu@Sun.COM 				autoc |= IXGBE_AUTOC_LMS_1G_AN;
8709353SSamuel.Tu@Sun.COM 			else
8719353SSamuel.Tu@Sun.COM 				autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
8729353SSamuel.Tu@Sun.COM 			}
8739353SSamuel.Tu@Sun.COM 	}
8749353SSamuel.Tu@Sun.COM 
87510305SPaul.Guo@Sun.COM 	if (autoc != start_autoc) {
8769353SSamuel.Tu@Sun.COM 		/* Restart link */
8779353SSamuel.Tu@Sun.COM 		autoc |= IXGBE_AUTOC_AN_RESTART;
8789353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
8799353SSamuel.Tu@Sun.COM 
8809353SSamuel.Tu@Sun.COM 		/* Only poll for autoneg to complete if specified to do so */
8819353SSamuel.Tu@Sun.COM 		if (autoneg_wait_to_complete) {
8829353SSamuel.Tu@Sun.COM 			if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
8839353SSamuel.Tu@Sun.COM 			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
8849353SSamuel.Tu@Sun.COM 			    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
8859353SSamuel.Tu@Sun.COM 				links_reg = 0; /* Just in case Autoneg time=0 */
8869353SSamuel.Tu@Sun.COM 				for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
8879353SSamuel.Tu@Sun.COM 					links_reg =
8889353SSamuel.Tu@Sun.COM 					    IXGBE_READ_REG(hw, IXGBE_LINKS);
8899353SSamuel.Tu@Sun.COM 					if (links_reg & IXGBE_LINKS_KX_AN_COMP)
8909353SSamuel.Tu@Sun.COM 						break;
8919353SSamuel.Tu@Sun.COM 					msec_delay(100);
8929353SSamuel.Tu@Sun.COM 				}
8939353SSamuel.Tu@Sun.COM 				if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
8949353SSamuel.Tu@Sun.COM 					status =
8959353SSamuel.Tu@Sun.COM 					    IXGBE_ERR_AUTONEG_NOT_COMPLETE;
8969353SSamuel.Tu@Sun.COM 					DEBUGOUT("Autoneg did not complete.\n");
8979353SSamuel.Tu@Sun.COM 				}
8989353SSamuel.Tu@Sun.COM 			}
8999353SSamuel.Tu@Sun.COM 		}
9009353SSamuel.Tu@Sun.COM 
9019353SSamuel.Tu@Sun.COM 		/* Add delay to filter out noises during initial link setup */
9029353SSamuel.Tu@Sun.COM 		msec_delay(50);
9039353SSamuel.Tu@Sun.COM 	}
9049353SSamuel.Tu@Sun.COM 
9059353SSamuel.Tu@Sun.COM out:
9069353SSamuel.Tu@Sun.COM 	return (status);
9079353SSamuel.Tu@Sun.COM }
9089353SSamuel.Tu@Sun.COM 
9099353SSamuel.Tu@Sun.COM /*
91010998SChenlu.Chen@Sun.COM  * ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field
9119353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
9129353SSamuel.Tu@Sun.COM  * @speed: new link speed
9139353SSamuel.Tu@Sun.COM  * @autoneg: true if autonegotiation enabled
9149353SSamuel.Tu@Sun.COM  * @autoneg_wait_to_complete: true if waiting is needed to complete
9159353SSamuel.Tu@Sun.COM  *
9169353SSamuel.Tu@Sun.COM  * Restarts link on PHY and MAC based on settings passed in.
9179353SSamuel.Tu@Sun.COM  */
9189353SSamuel.Tu@Sun.COM static s32
ixgbe_setup_copper_link_82599(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg,bool autoneg_wait_to_complete)91910998SChenlu.Chen@Sun.COM ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
9209353SSamuel.Tu@Sun.COM     ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete)
9219353SSamuel.Tu@Sun.COM {
9229353SSamuel.Tu@Sun.COM 	s32 status;
9239353SSamuel.Tu@Sun.COM 
92410998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_setup_copper_link_82599");
92510998SChenlu.Chen@Sun.COM 
9269353SSamuel.Tu@Sun.COM 	/* Setup the PHY according to input speed */
9279353SSamuel.Tu@Sun.COM 	status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
9289353SSamuel.Tu@Sun.COM 	    autoneg_wait_to_complete);
9299353SSamuel.Tu@Sun.COM 	/* Set up MAC */
93010998SChenlu.Chen@Sun.COM 	(void) ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete);
9319353SSamuel.Tu@Sun.COM 
9329353SSamuel.Tu@Sun.COM 	return (status);
9339353SSamuel.Tu@Sun.COM }
9349353SSamuel.Tu@Sun.COM /*
9359353SSamuel.Tu@Sun.COM  * ixgbe_reset_hw_82599 - Perform hardware reset
9369353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
9379353SSamuel.Tu@Sun.COM  *
9389353SSamuel.Tu@Sun.COM  * Resets the hardware by resetting the transmit and receive units, masks
9399353SSamuel.Tu@Sun.COM  * and clears all interrupts, perform a PHY reset, and perform a link (MAC)
9409353SSamuel.Tu@Sun.COM  * reset.
9419353SSamuel.Tu@Sun.COM  */
9429353SSamuel.Tu@Sun.COM s32
ixgbe_reset_hw_82599(struct ixgbe_hw * hw)9439353SSamuel.Tu@Sun.COM ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
9449353SSamuel.Tu@Sun.COM {
9459353SSamuel.Tu@Sun.COM 	s32 status = IXGBE_SUCCESS;
946*13006SChenlu.Chen@Sun.COM 	u32 ctrl;
9479353SSamuel.Tu@Sun.COM 	u32 i;
9489353SSamuel.Tu@Sun.COM 	u32 autoc;
9499353SSamuel.Tu@Sun.COM 	u32 autoc2;
9509353SSamuel.Tu@Sun.COM 
95110998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_reset_hw_82599");
95210998SChenlu.Chen@Sun.COM 
9539353SSamuel.Tu@Sun.COM 	/* Call adapter stop to disable tx/rx and clear interrupts */
9549353SSamuel.Tu@Sun.COM 	hw->mac.ops.stop_adapter(hw);
9559353SSamuel.Tu@Sun.COM 
9569353SSamuel.Tu@Sun.COM 	/* PHY ops must be identified and initialized prior to reset */
9579353SSamuel.Tu@Sun.COM 
9589353SSamuel.Tu@Sun.COM 	/* Identify PHY and related function pointers */
9599353SSamuel.Tu@Sun.COM 	status = hw->phy.ops.init(hw);
9609353SSamuel.Tu@Sun.COM 
96110305SPaul.Guo@Sun.COM 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
96210305SPaul.Guo@Sun.COM 		goto reset_hw_out;
96310305SPaul.Guo@Sun.COM 
9649353SSamuel.Tu@Sun.COM 	/* Setup SFP module if there is one present. */
9659353SSamuel.Tu@Sun.COM 	if (hw->phy.sfp_setup_needed) {
9669353SSamuel.Tu@Sun.COM 		status = hw->mac.ops.setup_sfp(hw);
9679353SSamuel.Tu@Sun.COM 		hw->phy.sfp_setup_needed = false;
9689353SSamuel.Tu@Sun.COM 	}
9699353SSamuel.Tu@Sun.COM 
97010305SPaul.Guo@Sun.COM 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
97110305SPaul.Guo@Sun.COM 		goto reset_hw_out;
97210305SPaul.Guo@Sun.COM 
9739353SSamuel.Tu@Sun.COM 	/* Reset PHY */
9749353SSamuel.Tu@Sun.COM 	if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
9759353SSamuel.Tu@Sun.COM 		hw->phy.ops.reset(hw);
9769353SSamuel.Tu@Sun.COM 
9779353SSamuel.Tu@Sun.COM 	/*
9789353SSamuel.Tu@Sun.COM 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
9799353SSamuel.Tu@Sun.COM 	 * access and verify no pending requests before reset
9809353SSamuel.Tu@Sun.COM 	 */
98112003SPaul.Guo@Sun.COM 	(void) ixgbe_disable_pcie_master(hw);
9829353SSamuel.Tu@Sun.COM 
98312003SPaul.Guo@Sun.COM mac_reset_top:
9849353SSamuel.Tu@Sun.COM 	/*
9859353SSamuel.Tu@Sun.COM 	 * Issue global reset to the MAC.  This needs to be a SW reset.
9869353SSamuel.Tu@Sun.COM 	 * If link reset is used, it might reset the MAC when mng is using it
9879353SSamuel.Tu@Sun.COM 	 */
9889353SSamuel.Tu@Sun.COM 	ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
9899353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST));
9909353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
9919353SSamuel.Tu@Sun.COM 
9929353SSamuel.Tu@Sun.COM 	/* Poll for reset bit to self-clear indicating reset is complete */
9939353SSamuel.Tu@Sun.COM 	for (i = 0; i < 10; i++) {
9949353SSamuel.Tu@Sun.COM 		usec_delay(1);
9959353SSamuel.Tu@Sun.COM 		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
9969353SSamuel.Tu@Sun.COM 		if (!(ctrl & IXGBE_CTRL_RST)) {
9979353SSamuel.Tu@Sun.COM 			break;
9989353SSamuel.Tu@Sun.COM 		}
9999353SSamuel.Tu@Sun.COM 	}
10009353SSamuel.Tu@Sun.COM 	if (ctrl & IXGBE_CTRL_RST) {
10019353SSamuel.Tu@Sun.COM 		status = IXGBE_ERR_RESET_FAILED;
10029353SSamuel.Tu@Sun.COM 		DEBUGOUT("Reset polling failed to complete.\n");
10039353SSamuel.Tu@Sun.COM 	}
10049353SSamuel.Tu@Sun.COM 
100512003SPaul.Guo@Sun.COM 	/*
100612003SPaul.Guo@Sun.COM 	 * Double resets are required for recovery from certain error
100712003SPaul.Guo@Sun.COM 	 * conditions.  Between resets, it is necessary to stall to allow time
100812003SPaul.Guo@Sun.COM 	 * for any pending HW events to complete.  We use 1usec since that is
100912003SPaul.Guo@Sun.COM 	 * what is needed for ixgbe_disable_pcie_master().  The second reset
101012003SPaul.Guo@Sun.COM 	 * then clears out any effects of those events.
101112003SPaul.Guo@Sun.COM 	 */
101212003SPaul.Guo@Sun.COM 	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
101312003SPaul.Guo@Sun.COM 		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
101412003SPaul.Guo@Sun.COM 		usec_delay(1);
101512003SPaul.Guo@Sun.COM 		goto mac_reset_top;
101612003SPaul.Guo@Sun.COM 	}
101712003SPaul.Guo@Sun.COM 
10189353SSamuel.Tu@Sun.COM 	msec_delay(50);
10199353SSamuel.Tu@Sun.COM 
10209353SSamuel.Tu@Sun.COM 	/*
10219353SSamuel.Tu@Sun.COM 	 * Store the original AUTOC/AUTOC2 values if they have not been
10229353SSamuel.Tu@Sun.COM 	 * stored off yet.  Otherwise restore the stored original
10239353SSamuel.Tu@Sun.COM 	 * values since the reset operation sets back to defaults.
10249353SSamuel.Tu@Sun.COM 	 */
10259353SSamuel.Tu@Sun.COM 	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
10269353SSamuel.Tu@Sun.COM 	autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
10279353SSamuel.Tu@Sun.COM 	if (hw->mac.orig_link_settings_stored == false) {
10289353SSamuel.Tu@Sun.COM 		hw->mac.orig_autoc = autoc;
10299353SSamuel.Tu@Sun.COM 		hw->mac.orig_autoc2 = autoc2;
10309353SSamuel.Tu@Sun.COM 		hw->mac.orig_link_settings_stored = true;
10319353SSamuel.Tu@Sun.COM 	} else {
10329353SSamuel.Tu@Sun.COM 		if (autoc != hw->mac.orig_autoc) {
10339353SSamuel.Tu@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc |
10349353SSamuel.Tu@Sun.COM 			    IXGBE_AUTOC_AN_RESTART));
10359353SSamuel.Tu@Sun.COM 		}
10369353SSamuel.Tu@Sun.COM 
10379353SSamuel.Tu@Sun.COM 		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
10389353SSamuel.Tu@Sun.COM 		    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
10399353SSamuel.Tu@Sun.COM 			autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
10409353SSamuel.Tu@Sun.COM 			autoc2 |= (hw->mac.orig_autoc2 &
10419353SSamuel.Tu@Sun.COM 			    IXGBE_AUTOC2_UPPER_MASK);
10429353SSamuel.Tu@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
10439353SSamuel.Tu@Sun.COM 		}
10449353SSamuel.Tu@Sun.COM 	}
10459353SSamuel.Tu@Sun.COM 
104610305SPaul.Guo@Sun.COM 	/* Store the permanent mac address */
104710305SPaul.Guo@Sun.COM 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
104810305SPaul.Guo@Sun.COM 
10499353SSamuel.Tu@Sun.COM 	/*
10509353SSamuel.Tu@Sun.COM 	 * Store MAC address from RAR0, clear receive address registers, and
10519353SSamuel.Tu@Sun.COM 	 * clear the multicast table.  Also reset num_rar_entries to 128,
10529353SSamuel.Tu@Sun.COM 	 * since we modify this value when programming the SAN MAC address.
10539353SSamuel.Tu@Sun.COM 	 */
10549353SSamuel.Tu@Sun.COM 	hw->mac.num_rar_entries = 128;
10559353SSamuel.Tu@Sun.COM 	hw->mac.ops.init_rx_addrs(hw);
10569353SSamuel.Tu@Sun.COM 
105710305SPaul.Guo@Sun.COM 	/* Store the permanent SAN mac address */
105810305SPaul.Guo@Sun.COM 	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
10599353SSamuel.Tu@Sun.COM 
10609353SSamuel.Tu@Sun.COM 	/* Add the SAN MAC address to the RAR only if it's a valid address */
10619353SSamuel.Tu@Sun.COM 	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
10629353SSamuel.Tu@Sun.COM 		hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
10639353SSamuel.Tu@Sun.COM 		    hw->mac.san_addr, 0, IXGBE_RAH_AV);
10649353SSamuel.Tu@Sun.COM 
10659353SSamuel.Tu@Sun.COM 		/* Reserve the last RAR for the SAN MAC address */
10669353SSamuel.Tu@Sun.COM 		hw->mac.num_rar_entries--;
10679353SSamuel.Tu@Sun.COM 	}
10689353SSamuel.Tu@Sun.COM 
106910998SChenlu.Chen@Sun.COM 	/* Store the alternative WWNN/WWPN prefix */
107010998SChenlu.Chen@Sun.COM 	hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
107110998SChenlu.Chen@Sun.COM 	    &hw->mac.wwpn_prefix);
107210998SChenlu.Chen@Sun.COM 
107310305SPaul.Guo@Sun.COM reset_hw_out:
10749353SSamuel.Tu@Sun.COM 	return (status);
10759353SSamuel.Tu@Sun.COM }
10769353SSamuel.Tu@Sun.COM 
10779353SSamuel.Tu@Sun.COM /*
10789353SSamuel.Tu@Sun.COM  * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
10799353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
10809353SSamuel.Tu@Sun.COM  */
10819353SSamuel.Tu@Sun.COM s32
ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw * hw)10829353SSamuel.Tu@Sun.COM ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
10839353SSamuel.Tu@Sun.COM {
108410305SPaul.Guo@Sun.COM 	int i;
10859353SSamuel.Tu@Sun.COM 	u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
10869353SSamuel.Tu@Sun.COM 	fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
108710305SPaul.Guo@Sun.COM 
108810998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_reinit_fdir_tables_82599");
108910998SChenlu.Chen@Sun.COM 
109010305SPaul.Guo@Sun.COM 	/*
109110305SPaul.Guo@Sun.COM 	 * Before starting reinitialization process,
109210305SPaul.Guo@Sun.COM 	 * FDIRCMD.CMD must be zero.
109310305SPaul.Guo@Sun.COM 	 */
109410305SPaul.Guo@Sun.COM 	for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
109510305SPaul.Guo@Sun.COM 		if (!(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
109610305SPaul.Guo@Sun.COM 		    IXGBE_FDIRCMD_CMD_MASK))
109710305SPaul.Guo@Sun.COM 			break;
109810305SPaul.Guo@Sun.COM 		usec_delay(10);
109910305SPaul.Guo@Sun.COM 	}
110010305SPaul.Guo@Sun.COM 	if (i >= IXGBE_FDIRCMD_CMD_POLL) {
110110305SPaul.Guo@Sun.COM 		DEBUGOUT("Flow Director previous command isn't complete, "
110210305SPaul.Guo@Sun.COM 		    "aborting table re-initialization. \n");
110310305SPaul.Guo@Sun.COM 		return (IXGBE_ERR_FDIR_REINIT_FAILED);
110410305SPaul.Guo@Sun.COM 	}
110510305SPaul.Guo@Sun.COM 
11069353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
11079353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
110810305SPaul.Guo@Sun.COM 	/*
110910305SPaul.Guo@Sun.COM 	 * 82599 adapters flow director init flow cannot be restarted,
111010305SPaul.Guo@Sun.COM 	 * Workaround 82599 silicon errata by performing the following steps
111110305SPaul.Guo@Sun.COM 	 * before re-writing the FDIRCTRL control register with the same value.
111210305SPaul.Guo@Sun.COM 	 * - write 1 to bit 8 of FDIRCMD register &
111310305SPaul.Guo@Sun.COM 	 * - write 0 to bit 8 of FDIRCMD register
111410305SPaul.Guo@Sun.COM 	 */
111510305SPaul.Guo@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
111610305SPaul.Guo@Sun.COM 	    (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
111710305SPaul.Guo@Sun.COM 	    IXGBE_FDIRCMD_CLEARHT));
111810305SPaul.Guo@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
111910305SPaul.Guo@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
112010305SPaul.Guo@Sun.COM 	    (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
112110305SPaul.Guo@Sun.COM 	    ~IXGBE_FDIRCMD_CLEARHT));
112210305SPaul.Guo@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
112310305SPaul.Guo@Sun.COM 	/*
112410305SPaul.Guo@Sun.COM 	 * Clear FDIR Hash register to clear any leftover hashes
112510305SPaul.Guo@Sun.COM 	 * waiting to be programmed.
112610305SPaul.Guo@Sun.COM 	 */
112710305SPaul.Guo@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00);
112810305SPaul.Guo@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
112910305SPaul.Guo@Sun.COM 
11309353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
113110305SPaul.Guo@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
113210305SPaul.Guo@Sun.COM 
113310305SPaul.Guo@Sun.COM 	/* Poll init-done after we write FDIRCTRL register */
113410305SPaul.Guo@Sun.COM 	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
113510305SPaul.Guo@Sun.COM 		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
113610305SPaul.Guo@Sun.COM 		    IXGBE_FDIRCTRL_INIT_DONE)
113710305SPaul.Guo@Sun.COM 			break;
113810305SPaul.Guo@Sun.COM 		usec_delay(10);
113910305SPaul.Guo@Sun.COM 	}
114010305SPaul.Guo@Sun.COM 	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
114110305SPaul.Guo@Sun.COM 		DEBUGOUT("Flow Director Signature poll time exceeded!\n");
114210305SPaul.Guo@Sun.COM 		return (IXGBE_ERR_FDIR_REINIT_FAILED);
114310305SPaul.Guo@Sun.COM 	}
114410305SPaul.Guo@Sun.COM 
114510305SPaul.Guo@Sun.COM 	/* Clear FDIR statistics registers (read to clear) */
114610305SPaul.Guo@Sun.COM 	(void) IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT);
114710305SPaul.Guo@Sun.COM 	(void) IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT);
114810305SPaul.Guo@Sun.COM 	(void) IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
114910305SPaul.Guo@Sun.COM 	(void) IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
115010305SPaul.Guo@Sun.COM 	(void) IXGBE_READ_REG(hw, IXGBE_FDIRLEN);
11519353SSamuel.Tu@Sun.COM 
11529353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
11539353SSamuel.Tu@Sun.COM }
11549353SSamuel.Tu@Sun.COM 
11559353SSamuel.Tu@Sun.COM /*
11569353SSamuel.Tu@Sun.COM  * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
11579353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
11589353SSamuel.Tu@Sun.COM  * @pballoc: which mode to allocate filters with
11599353SSamuel.Tu@Sun.COM  */
11609353SSamuel.Tu@Sun.COM s32
ixgbe_init_fdir_signature_82599(struct ixgbe_hw * hw,u32 pballoc)11619353SSamuel.Tu@Sun.COM ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc)
11629353SSamuel.Tu@Sun.COM {
11639353SSamuel.Tu@Sun.COM 	u32 fdirctrl = 0;
11649353SSamuel.Tu@Sun.COM 	u32 pbsize;
11659353SSamuel.Tu@Sun.COM 	int i;
11669353SSamuel.Tu@Sun.COM 
116710998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_init_fdir_signature_82599");
116810998SChenlu.Chen@Sun.COM 
11699353SSamuel.Tu@Sun.COM 	/*
11709353SSamuel.Tu@Sun.COM 	 * Before enabling Flow Director, the Rx Packet Buffer size
11719353SSamuel.Tu@Sun.COM 	 * must be reduced.  The new value is the current size minus
11729353SSamuel.Tu@Sun.COM 	 * flow director memory usage size.
11739353SSamuel.Tu@Sun.COM 	 */
11749353SSamuel.Tu@Sun.COM 	pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
11759353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
11769353SSamuel.Tu@Sun.COM 	    IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize);
11779353SSamuel.Tu@Sun.COM 
11789353SSamuel.Tu@Sun.COM 	/*
11799353SSamuel.Tu@Sun.COM 	 * The defaults in the HW for RX PB 1-7 are not zero and so should be
11809353SSamuel.Tu@Sun.COM 	 * intialized to zero for non DCB mode otherwise actual total RX PB
11819353SSamuel.Tu@Sun.COM 	 * would be bigger than programmed and filter space would run into
11829353SSamuel.Tu@Sun.COM 	 * the PB 0 region.
11839353SSamuel.Tu@Sun.COM 	 */
11849353SSamuel.Tu@Sun.COM 	for (i = 1; i < 8; i++)
11859353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
11869353SSamuel.Tu@Sun.COM 
11879353SSamuel.Tu@Sun.COM 	/* Send interrupt when 64 filters are left */
11889353SSamuel.Tu@Sun.COM 	fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
11899353SSamuel.Tu@Sun.COM 
11909353SSamuel.Tu@Sun.COM 	/* Set the maximum length per hash bucket to 0xA filters */
11919353SSamuel.Tu@Sun.COM 	fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT;
11929353SSamuel.Tu@Sun.COM 
11939353SSamuel.Tu@Sun.COM 	switch (pballoc) {
11949353SSamuel.Tu@Sun.COM 	case IXGBE_FDIR_PBALLOC_64K:
11959353SSamuel.Tu@Sun.COM 		/* 8k - 1 signature filters */
11969353SSamuel.Tu@Sun.COM 		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
11979353SSamuel.Tu@Sun.COM 		break;
11989353SSamuel.Tu@Sun.COM 	case IXGBE_FDIR_PBALLOC_128K:
11999353SSamuel.Tu@Sun.COM 		/* 16k - 1 signature filters */
12009353SSamuel.Tu@Sun.COM 		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
12019353SSamuel.Tu@Sun.COM 		break;
12029353SSamuel.Tu@Sun.COM 	case IXGBE_FDIR_PBALLOC_256K:
12039353SSamuel.Tu@Sun.COM 		/* 32k - 1 signature filters */
12049353SSamuel.Tu@Sun.COM 		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
12059353SSamuel.Tu@Sun.COM 		break;
12069353SSamuel.Tu@Sun.COM 	default:
12079353SSamuel.Tu@Sun.COM 		/* bad value */
12089353SSamuel.Tu@Sun.COM 		return (IXGBE_ERR_CONFIG);
12099353SSamuel.Tu@Sun.COM 	};
12109353SSamuel.Tu@Sun.COM 
12119353SSamuel.Tu@Sun.COM 	/* Move the flexible bytes to use the ethertype - shift 6 words */
12129353SSamuel.Tu@Sun.COM 	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
12139353SSamuel.Tu@Sun.COM 
12149353SSamuel.Tu@Sun.COM 	/* Prime the keys for hashing */
12159353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
12169353SSamuel.Tu@Sun.COM 	    IXGBE_HTONL(IXGBE_ATR_BUCKET_HASH_KEY));
12179353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
12189353SSamuel.Tu@Sun.COM 	    IXGBE_HTONL(IXGBE_ATR_SIGNATURE_HASH_KEY));
12199353SSamuel.Tu@Sun.COM 
12209353SSamuel.Tu@Sun.COM 	/*
12219353SSamuel.Tu@Sun.COM 	 * Poll init-done after we write the register.  Estimated times:
12229353SSamuel.Tu@Sun.COM 	 *   10G: PBALLOC = 11b, timing is 60us
12239353SSamuel.Tu@Sun.COM 	 *    1G: PBALLOC = 11b, timing is 600us
12249353SSamuel.Tu@Sun.COM 	 *  100M: PBALLOC = 11b, timing is 6ms
12259353SSamuel.Tu@Sun.COM 	 *
12269353SSamuel.Tu@Sun.COM 	 *   Multiple these timings by 4 if under full Rx load
12279353SSamuel.Tu@Sun.COM 	 *
12289353SSamuel.Tu@Sun.COM 	 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
12299353SSamuel.Tu@Sun.COM 	 * 1 msec per poll time.  If we're at line rate and drop to 100M, then
12309353SSamuel.Tu@Sun.COM 	 * this might not finish in our poll time, but we can live with that
12319353SSamuel.Tu@Sun.COM 	 * for now.
12329353SSamuel.Tu@Sun.COM 	 */
12339353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
12349353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
12359353SSamuel.Tu@Sun.COM 	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
12369353SSamuel.Tu@Sun.COM 		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
12379353SSamuel.Tu@Sun.COM 		    IXGBE_FDIRCTRL_INIT_DONE)
12389353SSamuel.Tu@Sun.COM 			break;
12399353SSamuel.Tu@Sun.COM 
12409353SSamuel.Tu@Sun.COM 		msec_delay(1);
12419353SSamuel.Tu@Sun.COM 	}
12429353SSamuel.Tu@Sun.COM 	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
12439353SSamuel.Tu@Sun.COM 		DEBUGOUT("Flow Director Signature poll time exceeded!\n");
12449353SSamuel.Tu@Sun.COM 	}
12459353SSamuel.Tu@Sun.COM 
12469353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
12479353SSamuel.Tu@Sun.COM }
12489353SSamuel.Tu@Sun.COM 
12499353SSamuel.Tu@Sun.COM /*
12509353SSamuel.Tu@Sun.COM  * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
12519353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
12529353SSamuel.Tu@Sun.COM  * @pballoc: which mode to allocate filters with
12539353SSamuel.Tu@Sun.COM  */
12549353SSamuel.Tu@Sun.COM s32
ixgbe_init_fdir_perfect_82599(struct ixgbe_hw * hw,u32 pballoc)12559353SSamuel.Tu@Sun.COM ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
12569353SSamuel.Tu@Sun.COM {
12579353SSamuel.Tu@Sun.COM 	u32 fdirctrl = 0;
12589353SSamuel.Tu@Sun.COM 	u32 pbsize;
12599353SSamuel.Tu@Sun.COM 	int i;
12609353SSamuel.Tu@Sun.COM 
126110998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_init_fdir_perfect_82599");
126210998SChenlu.Chen@Sun.COM 
12639353SSamuel.Tu@Sun.COM 	/*
12649353SSamuel.Tu@Sun.COM 	 * Before enabling Flow Director, the Rx Packet Buffer size
12659353SSamuel.Tu@Sun.COM 	 * must be reduced.  The new value is the current size minus
12669353SSamuel.Tu@Sun.COM 	 * flow director memory usage size.
12679353SSamuel.Tu@Sun.COM 	 */
12689353SSamuel.Tu@Sun.COM 
12699353SSamuel.Tu@Sun.COM 	pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
12709353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
12719353SSamuel.Tu@Sun.COM 	    IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize);
12729353SSamuel.Tu@Sun.COM 
12739353SSamuel.Tu@Sun.COM 	/*
12749353SSamuel.Tu@Sun.COM 	 * The defaults in the HW for RX PB 1-7 are not zero and so should be
12759353SSamuel.Tu@Sun.COM 	 * intialized to zero for non DCB mode otherwise actual total RX PB
12769353SSamuel.Tu@Sun.COM 	 * would be bigger than programmed and filter space would run into
12779353SSamuel.Tu@Sun.COM 	 * the PB 0 region.
12789353SSamuel.Tu@Sun.COM 	 */
12799353SSamuel.Tu@Sun.COM 	for (i = 1; i < 8; i++)
12809353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
12819353SSamuel.Tu@Sun.COM 
12829353SSamuel.Tu@Sun.COM 	/* Send interrupt when 64 filters are left */
12839353SSamuel.Tu@Sun.COM 	fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
12849353SSamuel.Tu@Sun.COM 
1285*13006SChenlu.Chen@Sun.COM 	/* Initialize the drop queue to Rx queue 127 */
1286*13006SChenlu.Chen@Sun.COM 	fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
1287*13006SChenlu.Chen@Sun.COM 
12889353SSamuel.Tu@Sun.COM 	switch (pballoc) {
12899353SSamuel.Tu@Sun.COM 	case IXGBE_FDIR_PBALLOC_64K:
12909353SSamuel.Tu@Sun.COM 		/* 2k - 1 perfect filters */
12919353SSamuel.Tu@Sun.COM 		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
12929353SSamuel.Tu@Sun.COM 		break;
12939353SSamuel.Tu@Sun.COM 	case IXGBE_FDIR_PBALLOC_128K:
12949353SSamuel.Tu@Sun.COM 		/* 4k - 1 perfect filters */
12959353SSamuel.Tu@Sun.COM 		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
12969353SSamuel.Tu@Sun.COM 		break;
12979353SSamuel.Tu@Sun.COM 	case IXGBE_FDIR_PBALLOC_256K:
12989353SSamuel.Tu@Sun.COM 		/* 8k - 1 perfect filters */
12999353SSamuel.Tu@Sun.COM 		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
13009353SSamuel.Tu@Sun.COM 		break;
13019353SSamuel.Tu@Sun.COM 	default:
13029353SSamuel.Tu@Sun.COM 		/* bad value */
13039353SSamuel.Tu@Sun.COM 		return (IXGBE_ERR_CONFIG);
13049353SSamuel.Tu@Sun.COM 	};
13059353SSamuel.Tu@Sun.COM 
13069353SSamuel.Tu@Sun.COM 	/* Turn perfect match filtering on */
13079353SSamuel.Tu@Sun.COM 	fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
13089353SSamuel.Tu@Sun.COM 	fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
13099353SSamuel.Tu@Sun.COM 
13109353SSamuel.Tu@Sun.COM 	/* Move the flexible bytes to use the ethertype - shift 6 words */
13119353SSamuel.Tu@Sun.COM 	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
13129353SSamuel.Tu@Sun.COM 
13139353SSamuel.Tu@Sun.COM 	/* Prime the keys for hashing */
13149353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
13159353SSamuel.Tu@Sun.COM 	    IXGBE_HTONL(IXGBE_ATR_BUCKET_HASH_KEY));
13169353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
13179353SSamuel.Tu@Sun.COM 	    IXGBE_HTONL(IXGBE_ATR_SIGNATURE_HASH_KEY));
13189353SSamuel.Tu@Sun.COM 
13199353SSamuel.Tu@Sun.COM 	/*
13209353SSamuel.Tu@Sun.COM 	 * Poll init-done after we write the register.  Estimated times:
13219353SSamuel.Tu@Sun.COM 	 *   10G: PBALLOC = 11b, timing is 60us
13229353SSamuel.Tu@Sun.COM 	 *    1G: PBALLOC = 11b, timing is 600us
13239353SSamuel.Tu@Sun.COM 	 *  100M: PBALLOC = 11b, timing is 6ms
13249353SSamuel.Tu@Sun.COM 	 *
13259353SSamuel.Tu@Sun.COM 	 *  Multiple these timings by 4 if under full Rx load
13269353SSamuel.Tu@Sun.COM 	 *
13279353SSamuel.Tu@Sun.COM 	 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
13289353SSamuel.Tu@Sun.COM 	 * 1 msec per poll time.  If we're at line rate and drop to 100M, then
13299353SSamuel.Tu@Sun.COM 	 * this might not finish in our poll time, but we can live with that
13309353SSamuel.Tu@Sun.COM 	 * for now.
13319353SSamuel.Tu@Sun.COM 	 */
13329353SSamuel.Tu@Sun.COM 
13339353SSamuel.Tu@Sun.COM 	/* Set the maximum length per hash bucket to 0xA filters */
13349353SSamuel.Tu@Sun.COM 	fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT);
13359353SSamuel.Tu@Sun.COM 
13369353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
13379353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
13389353SSamuel.Tu@Sun.COM 	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
13399353SSamuel.Tu@Sun.COM 		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
13409353SSamuel.Tu@Sun.COM 		    IXGBE_FDIRCTRL_INIT_DONE)
13419353SSamuel.Tu@Sun.COM 			break;
13429353SSamuel.Tu@Sun.COM 
13439353SSamuel.Tu@Sun.COM 		msec_delay(1);
13449353SSamuel.Tu@Sun.COM 	}
13459353SSamuel.Tu@Sun.COM 	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
13469353SSamuel.Tu@Sun.COM 		DEBUGOUT("Flow Director Perfect poll time exceeded!\n");
13479353SSamuel.Tu@Sun.COM 	}
13489353SSamuel.Tu@Sun.COM 
13499353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
13509353SSamuel.Tu@Sun.COM }
13519353SSamuel.Tu@Sun.COM 
13529353SSamuel.Tu@Sun.COM /*
13539353SSamuel.Tu@Sun.COM  * ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
13549353SSamuel.Tu@Sun.COM  * @stream: input bitstream to compute the hash on
13559353SSamuel.Tu@Sun.COM  * @key: 32-bit hash key
13569353SSamuel.Tu@Sun.COM  */
13579353SSamuel.Tu@Sun.COM u16
ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input * atr_input,u32 key)13589353SSamuel.Tu@Sun.COM ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, u32 key)
13599353SSamuel.Tu@Sun.COM {
13609353SSamuel.Tu@Sun.COM 	/*
13619353SSamuel.Tu@Sun.COM 	 * The algorithm is as follows:
13629353SSamuel.Tu@Sun.COM 	 *    Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
13639353SSamuel.Tu@Sun.COM 	 *    where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
13649353SSamuel.Tu@Sun.COM 	 *    and A[n] x B[n] is bitwise AND between same length strings
13659353SSamuel.Tu@Sun.COM 	 *
13669353SSamuel.Tu@Sun.COM 	 *    K[n] is 16 bits, defined as:
13679353SSamuel.Tu@Sun.COM 	 *	for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
13689353SSamuel.Tu@Sun.COM 	 *	for n modulo 32 < 15, K[n] =
13699353SSamuel.Tu@Sun.COM 	 *		K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
13709353SSamuel.Tu@Sun.COM 	 *
13719353SSamuel.Tu@Sun.COM 	 *    S[n] is 16 bits, defined as:
13729353SSamuel.Tu@Sun.COM 	 *	for n >= 15, S[n] = S[n:n - 15]
13739353SSamuel.Tu@Sun.COM 	 *	for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
13749353SSamuel.Tu@Sun.COM 	 *
13759353SSamuel.Tu@Sun.COM 	 *    To simplify for programming, the algorithm is implemented
13769353SSamuel.Tu@Sun.COM 	 *    in software this way:
13779353SSamuel.Tu@Sun.COM 	 *
13789353SSamuel.Tu@Sun.COM 	 *    Key[31:0], Stream[335:0]
13799353SSamuel.Tu@Sun.COM 	 *
13809353SSamuel.Tu@Sun.COM 	 *    tmp_key[11 * 32 - 1:0] = 11{Key[31:0] = key concatenated 11 times
13819353SSamuel.Tu@Sun.COM 	 *    int_key[350:0] = tmp_key[351:1]
13829353SSamuel.Tu@Sun.COM 	 *    int_stream[365:0] = Stream[14:0] | Stream[335:0] | Stream[335:321]
13839353SSamuel.Tu@Sun.COM 	 *
13849353SSamuel.Tu@Sun.COM 	 *    hash[15:0] = 0;
13859353SSamuel.Tu@Sun.COM 	 *    for (i = 0; i < 351; i++) {
13869353SSamuel.Tu@Sun.COM 	 *	if (int_key[i])
138710305SPaul.Guo@Sun.COM 	 *		hash ^= int_stream[(i + 15):i];
13889353SSamuel.Tu@Sun.COM 	 *    }
13899353SSamuel.Tu@Sun.COM 	 */
13909353SSamuel.Tu@Sun.COM 
13919353SSamuel.Tu@Sun.COM 	union {
139210305SPaul.Guo@Sun.COM 		u64 fill[6];
139310305SPaul.Guo@Sun.COM 		u32 key[11];
139410305SPaul.Guo@Sun.COM 		u8 key_stream[44];
13959353SSamuel.Tu@Sun.COM 	} tmp_key;
13969353SSamuel.Tu@Sun.COM 
13979353SSamuel.Tu@Sun.COM 	u8 *stream = (u8 *)atr_input;
13989353SSamuel.Tu@Sun.COM 	u8 int_key[44];		/* upper-most bit unused */
13999353SSamuel.Tu@Sun.COM 	u8 hash_str[46];	/* upper-most 2 bits unused */
14009353SSamuel.Tu@Sun.COM 	u16 hash_result = 0;
14019353SSamuel.Tu@Sun.COM 	int i, j, k, h;
14029353SSamuel.Tu@Sun.COM 
140310998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_compute_hash_82599");
140410998SChenlu.Chen@Sun.COM 
140510305SPaul.Guo@Sun.COM 	/*
140610305SPaul.Guo@Sun.COM 	 * Initialize the fill member to prevent warnings
140710305SPaul.Guo@Sun.COM 	 * on some compilers
140810305SPaul.Guo@Sun.COM 	 */
140910305SPaul.Guo@Sun.COM 	tmp_key.fill[0] = 0;
141010305SPaul.Guo@Sun.COM 
14119353SSamuel.Tu@Sun.COM 	/* First load the temporary key stream */
141210305SPaul.Guo@Sun.COM 	for (i = 0; i < 6; i++) {
141310305SPaul.Guo@Sun.COM 		u64 fillkey = ((u64)key << 32) | key;
141410305SPaul.Guo@Sun.COM 		tmp_key.fill[i] = fillkey;
141510305SPaul.Guo@Sun.COM 	}
14169353SSamuel.Tu@Sun.COM 
14179353SSamuel.Tu@Sun.COM 	/*
14189353SSamuel.Tu@Sun.COM 	 * Set the interim key for the hashing.  Bit 352 is unused, so we must
14199353SSamuel.Tu@Sun.COM 	 * shift and compensate when building the key.
14209353SSamuel.Tu@Sun.COM 	 */
14219353SSamuel.Tu@Sun.COM 	int_key[0] = tmp_key.key_stream[0] >> 1;
14229353SSamuel.Tu@Sun.COM 	for (i = 1, j = 0; i < 44; i++) {
142310305SPaul.Guo@Sun.COM 		unsigned int this_key = tmp_key.key_stream[j] << 7;
14249353SSamuel.Tu@Sun.COM 		j++;
142510305SPaul.Guo@Sun.COM 		int_key[i] = (u8)(this_key | (tmp_key.key_stream[j] >> 1));
14269353SSamuel.Tu@Sun.COM 	}
14279353SSamuel.Tu@Sun.COM 
14289353SSamuel.Tu@Sun.COM 	/*
14299353SSamuel.Tu@Sun.COM 	 * Set the interim bit string for the hashing.  Bits 368 and 367 are
14309353SSamuel.Tu@Sun.COM 	 * unused, so shift and compensate when building the string.
14319353SSamuel.Tu@Sun.COM 	 */
14329353SSamuel.Tu@Sun.COM 	hash_str[0] = (stream[40] & 0x7f) >> 1;
14339353SSamuel.Tu@Sun.COM 	for (i = 1, j = 40; i < 46; i++) {
143410305SPaul.Guo@Sun.COM 		unsigned int this_str = stream[j] << 7;
14359353SSamuel.Tu@Sun.COM 		j++;
14369353SSamuel.Tu@Sun.COM 		if (j > 41)
14379353SSamuel.Tu@Sun.COM 			j = 0;
143810305SPaul.Guo@Sun.COM 		hash_str[i] = (u8)(this_str | (stream[j] >> 1));
14399353SSamuel.Tu@Sun.COM 	}
14409353SSamuel.Tu@Sun.COM 
14419353SSamuel.Tu@Sun.COM 	/*
14429353SSamuel.Tu@Sun.COM 	 * Now compute the hash.  i is the index into hash_str, j is into our
14439353SSamuel.Tu@Sun.COM 	 * key stream, k is counting the number of bits, and h interates within
14449353SSamuel.Tu@Sun.COM 	 * each byte.
14459353SSamuel.Tu@Sun.COM 	 */
14469353SSamuel.Tu@Sun.COM 	for (i = 45, j = 43, k = 0; k < 351 && i >= 2 && j >= 0; i--, j--) {
14479353SSamuel.Tu@Sun.COM 		for (h = 0; h < 8 && k < 351; h++, k++) {
144810305SPaul.Guo@Sun.COM 			if (int_key[j] & (1 << h)) {
14499353SSamuel.Tu@Sun.COM 				/*
14509353SSamuel.Tu@Sun.COM 				 * Key bit is set, XOR in the current 16-bit
14519353SSamuel.Tu@Sun.COM 				 * string.  Example of processing:
14529353SSamuel.Tu@Sun.COM 				 *	h = 0,
14539353SSamuel.Tu@Sun.COM 				 *	tmp = (hash_str[i - 2] & 0 << 16) |
14549353SSamuel.Tu@Sun.COM 				 *		(hash_str[i - 1] & 0xff << 8) |
14559353SSamuel.Tu@Sun.COM 				 *		(hash_str[i] & 0xff >> 0)
14569353SSamuel.Tu@Sun.COM 				 *	So tmp = hash_str[15 + k:k], since the
14579353SSamuel.Tu@Sun.COM 				 *	i + 2 clause rolls off the 16-bit value
14589353SSamuel.Tu@Sun.COM 				 *	h = 7,
14599353SSamuel.Tu@Sun.COM 				 *	tmp = (hash_str[i - 2] & 0x7f << 9) |
14609353SSamuel.Tu@Sun.COM 				 *		(hash_str[i - 1] & 0xff << 1) |
14619353SSamuel.Tu@Sun.COM 				 *		(hash_str[i] & 0x80 >> 7)
14629353SSamuel.Tu@Sun.COM 				 */
146310305SPaul.Guo@Sun.COM 				int tmp = (hash_str[i] >> h);
146410305SPaul.Guo@Sun.COM 				tmp |= (hash_str[i - 1] << (8 - h));
146510305SPaul.Guo@Sun.COM 				tmp |= (int)(hash_str[i - 2] & ((1 << h) - 1))
14669353SSamuel.Tu@Sun.COM 				    << (16 - h);
146710305SPaul.Guo@Sun.COM 				hash_result ^= (u16)tmp;
14689353SSamuel.Tu@Sun.COM 			}
14699353SSamuel.Tu@Sun.COM 		}
14709353SSamuel.Tu@Sun.COM 	}
14719353SSamuel.Tu@Sun.COM 
14729353SSamuel.Tu@Sun.COM 	return (hash_result);
14739353SSamuel.Tu@Sun.COM }
14749353SSamuel.Tu@Sun.COM 
14759353SSamuel.Tu@Sun.COM /*
14769353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream
14779353SSamuel.Tu@Sun.COM  * @input: input stream to modify
14789353SSamuel.Tu@Sun.COM  * @vlan: the VLAN id to load
14799353SSamuel.Tu@Sun.COM  */
14809353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input * input,u16 vlan)14819353SSamuel.Tu@Sun.COM ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan)
14829353SSamuel.Tu@Sun.COM {
148310998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_vlan_id_82599");
148410998SChenlu.Chen@Sun.COM 
14859353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] = vlan >> 8;
14869353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_VLAN_OFFSET] = vlan & 0xff;
14879353SSamuel.Tu@Sun.COM 
14889353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
14899353SSamuel.Tu@Sun.COM }
14909353SSamuel.Tu@Sun.COM 
14919353SSamuel.Tu@Sun.COM /*
14929353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address
14939353SSamuel.Tu@Sun.COM  * @input: input stream to modify
14949353SSamuel.Tu@Sun.COM  * @src_addr: the IP address to load
14959353SSamuel.Tu@Sun.COM  */
14969353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input * input,u32 src_addr)14979353SSamuel.Tu@Sun.COM ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr)
14989353SSamuel.Tu@Sun.COM {
149910998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_src_ipv4_82599");
150010998SChenlu.Chen@Sun.COM 
15019353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] = src_addr >> 24;
15029353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] =
15039353SSamuel.Tu@Sun.COM 	    (src_addr >> 16) & 0xff;
15049353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] =
15059353SSamuel.Tu@Sun.COM 	    (src_addr >> 8) & 0xff;
15069353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET] = src_addr & 0xff;
15079353SSamuel.Tu@Sun.COM 
15089353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
15099353SSamuel.Tu@Sun.COM }
15109353SSamuel.Tu@Sun.COM 
15119353SSamuel.Tu@Sun.COM /*
15129353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address
15139353SSamuel.Tu@Sun.COM  * @input: input stream to modify
15149353SSamuel.Tu@Sun.COM  * @dst_addr: the IP address to load
15159353SSamuel.Tu@Sun.COM  */
15169353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input * input,u32 dst_addr)15179353SSamuel.Tu@Sun.COM ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr)
15189353SSamuel.Tu@Sun.COM {
151910998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_dst_ipv4_82599");
152010998SChenlu.Chen@Sun.COM 
15219353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] = dst_addr >> 24;
15229353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] =
15239353SSamuel.Tu@Sun.COM 	    (dst_addr >> 16) & 0xff;
15249353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] =
15259353SSamuel.Tu@Sun.COM 	    (dst_addr >> 8) & 0xff;
15269353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET] = dst_addr & 0xff;
15279353SSamuel.Tu@Sun.COM 
15289353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
15299353SSamuel.Tu@Sun.COM }
15309353SSamuel.Tu@Sun.COM 
15319353SSamuel.Tu@Sun.COM /*
15329353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_src_ipv6_82599 - Sets the source IPv6 address
15339353SSamuel.Tu@Sun.COM  * @input: input stream to modify
15349353SSamuel.Tu@Sun.COM  * @src_addr_1: the first 4 bytes of the IP address to load
15359353SSamuel.Tu@Sun.COM  * @src_addr_2: the second 4 bytes of the IP address to load
15369353SSamuel.Tu@Sun.COM  * @src_addr_3: the third 4 bytes of the IP address to load
15379353SSamuel.Tu@Sun.COM  * @src_addr_4: the fourth 4 bytes of the IP address to load
15389353SSamuel.Tu@Sun.COM  */
15399353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input * input,u32 src_addr_1,u32 src_addr_2,u32 src_addr_3,u32 src_addr_4)15409353SSamuel.Tu@Sun.COM ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
15419353SSamuel.Tu@Sun.COM     u32 src_addr_1, u32 src_addr_2, u32 src_addr_3, u32 src_addr_4)
15429353SSamuel.Tu@Sun.COM {
154310998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_src_ipv6_82599");
154410998SChenlu.Chen@Sun.COM 
15459353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff;
15469353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] =
15479353SSamuel.Tu@Sun.COM 	    (src_addr_4 >> 8) & 0xff;
15489353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] =
15499353SSamuel.Tu@Sun.COM 	    (src_addr_4 >> 16) & 0xff;
15509353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] = src_addr_4 >> 24;
15519353SSamuel.Tu@Sun.COM 
15529353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4] = src_addr_3 & 0xff;
15539353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] =
15549353SSamuel.Tu@Sun.COM 	    (src_addr_3 >> 8) & 0xff;
15559353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] =
15569353SSamuel.Tu@Sun.COM 	    (src_addr_3 >> 16) & 0xff;
15579353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] = src_addr_3 >> 24;
15589353SSamuel.Tu@Sun.COM 
15599353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8] = src_addr_2 & 0xff;
15609353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] =
15619353SSamuel.Tu@Sun.COM 	    (src_addr_2 >> 8) & 0xff;
15629353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] =
15639353SSamuel.Tu@Sun.COM 	    (src_addr_2 >> 16) & 0xff;
15649353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] = src_addr_2 >> 24;
15659353SSamuel.Tu@Sun.COM 
15669353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12] = src_addr_1 & 0xff;
15679353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] =
15689353SSamuel.Tu@Sun.COM 	    (src_addr_1 >> 8) & 0xff;
15699353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] =
15709353SSamuel.Tu@Sun.COM 	    (src_addr_1 >> 16) & 0xff;
15719353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] = src_addr_1 >> 24;
15729353SSamuel.Tu@Sun.COM 
15739353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
15749353SSamuel.Tu@Sun.COM }
15759353SSamuel.Tu@Sun.COM 
15769353SSamuel.Tu@Sun.COM /*
15779353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_dst_ipv6_82599 - Sets the destination IPv6 address
15789353SSamuel.Tu@Sun.COM  * @input: input stream to modify
15799353SSamuel.Tu@Sun.COM  * @dst_addr_1: the first 4 bytes of the IP address to load
15809353SSamuel.Tu@Sun.COM  * @dst_addr_2: the second 4 bytes of the IP address to load
15819353SSamuel.Tu@Sun.COM  * @dst_addr_3: the third 4 bytes of the IP address to load
15829353SSamuel.Tu@Sun.COM  * @dst_addr_4: the fourth 4 bytes of the IP address to load
15839353SSamuel.Tu@Sun.COM  */
15849353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input * input,u32 dst_addr_1,u32 dst_addr_2,u32 dst_addr_3,u32 dst_addr_4)15859353SSamuel.Tu@Sun.COM ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
15869353SSamuel.Tu@Sun.COM     u32 dst_addr_1, u32 dst_addr_2, u32 dst_addr_3, u32 dst_addr_4)
15879353SSamuel.Tu@Sun.COM {
158810998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_dst_ipv6_82599");
158910998SChenlu.Chen@Sun.COM 
15909353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff;
15919353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] =
15929353SSamuel.Tu@Sun.COM 	    (dst_addr_4 >> 8) & 0xff;
15939353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] =
15949353SSamuel.Tu@Sun.COM 	    (dst_addr_4 >> 16) & 0xff;
15959353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] = dst_addr_4 >> 24;
15969353SSamuel.Tu@Sun.COM 
15979353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4] = dst_addr_3 & 0xff;
15989353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] =
15999353SSamuel.Tu@Sun.COM 	    (dst_addr_3 >> 8) & 0xff;
16009353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] =
16019353SSamuel.Tu@Sun.COM 	    (dst_addr_3 >> 16) & 0xff;
16029353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] = dst_addr_3 >> 24;
16039353SSamuel.Tu@Sun.COM 
16049353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8] = dst_addr_2 & 0xff;
16059353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] =
16069353SSamuel.Tu@Sun.COM 	    (dst_addr_2 >> 8) & 0xff;
16079353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] =
16089353SSamuel.Tu@Sun.COM 	    (dst_addr_2 >> 16) & 0xff;
16099353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] = dst_addr_2 >> 24;
16109353SSamuel.Tu@Sun.COM 
16119353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12] = dst_addr_1 & 0xff;
16129353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] =
16139353SSamuel.Tu@Sun.COM 	    (dst_addr_1 >> 8) & 0xff;
16149353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] =
16159353SSamuel.Tu@Sun.COM 	    (dst_addr_1 >> 16) & 0xff;
16169353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] = dst_addr_1 >> 24;
16179353SSamuel.Tu@Sun.COM 
16189353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
16199353SSamuel.Tu@Sun.COM }
16209353SSamuel.Tu@Sun.COM 
16219353SSamuel.Tu@Sun.COM /*
16229353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_src_port_82599 - Sets the source port
16239353SSamuel.Tu@Sun.COM  * @input: input stream to modify
16249353SSamuel.Tu@Sun.COM  * @src_port: the source port to load
16259353SSamuel.Tu@Sun.COM  */
16269353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input * input,u16 src_port)16279353SSamuel.Tu@Sun.COM ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port)
16289353SSamuel.Tu@Sun.COM {
162910998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_src_port_82599");
163010998SChenlu.Chen@Sun.COM 
16319353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1] = src_port >> 8;
16329353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] = src_port & 0xff;
16339353SSamuel.Tu@Sun.COM 
16349353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
16359353SSamuel.Tu@Sun.COM }
16369353SSamuel.Tu@Sun.COM 
16379353SSamuel.Tu@Sun.COM /*
16389353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_dst_port_82599 - Sets the destination port
16399353SSamuel.Tu@Sun.COM  * @input: input stream to modify
16409353SSamuel.Tu@Sun.COM  * @dst_port: the destination port to load
16419353SSamuel.Tu@Sun.COM  */
16429353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input * input,u16 dst_port)16439353SSamuel.Tu@Sun.COM ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port)
16449353SSamuel.Tu@Sun.COM {
164510998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_dst_port_82599");
164610998SChenlu.Chen@Sun.COM 
16479353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1] = dst_port >> 8;
16489353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] = dst_port & 0xff;
16499353SSamuel.Tu@Sun.COM 
16509353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
16519353SSamuel.Tu@Sun.COM }
16529353SSamuel.Tu@Sun.COM 
16539353SSamuel.Tu@Sun.COM /*
16549353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_flex_byte_82599 - Sets the flexible bytes
16559353SSamuel.Tu@Sun.COM  * @input: input stream to modify
16569353SSamuel.Tu@Sun.COM  * @flex_bytes: the flexible bytes to load
16579353SSamuel.Tu@Sun.COM  */
16589353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input * input,u16 flex_byte)16599353SSamuel.Tu@Sun.COM ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte)
16609353SSamuel.Tu@Sun.COM {
166110998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_flex_byte_82599");
166210998SChenlu.Chen@Sun.COM 
16639353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] = flex_byte >> 8;
16649353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET] = flex_byte & 0xff;
16659353SSamuel.Tu@Sun.COM 
16669353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
16679353SSamuel.Tu@Sun.COM }
16689353SSamuel.Tu@Sun.COM 
16699353SSamuel.Tu@Sun.COM /*
16709353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_vm_pool_82599 - Sets the Virtual Machine pool
16719353SSamuel.Tu@Sun.COM  * @input: input stream to modify
16729353SSamuel.Tu@Sun.COM  * @vm_pool: the Virtual Machine pool to load
16739353SSamuel.Tu@Sun.COM  */
16749353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input * input,u8 vm_pool)16759353SSamuel.Tu@Sun.COM ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool)
16769353SSamuel.Tu@Sun.COM {
167710998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_vm_pool_82599");
167810998SChenlu.Chen@Sun.COM 
16799353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool;
16809353SSamuel.Tu@Sun.COM 
16819353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
16829353SSamuel.Tu@Sun.COM }
16839353SSamuel.Tu@Sun.COM 
16849353SSamuel.Tu@Sun.COM /*
16859353SSamuel.Tu@Sun.COM  * ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type
16869353SSamuel.Tu@Sun.COM  * @input: input stream to modify
16879353SSamuel.Tu@Sun.COM  * @l4type: the layer 4 type value to load
16889353SSamuel.Tu@Sun.COM  */
16899353SSamuel.Tu@Sun.COM s32
ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input * input,u8 l4type)16909353SSamuel.Tu@Sun.COM ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type)
16919353SSamuel.Tu@Sun.COM {
169210998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_set_l4type_82599");
169310998SChenlu.Chen@Sun.COM 
16949353SSamuel.Tu@Sun.COM 	input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type;
16959353SSamuel.Tu@Sun.COM 
16969353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
16979353SSamuel.Tu@Sun.COM }
16989353SSamuel.Tu@Sun.COM 
16999353SSamuel.Tu@Sun.COM /*
17009353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_vlan_id_82599 - Gets the VLAN id from the ATR input stream
17019353SSamuel.Tu@Sun.COM  * @input: input stream to search
17029353SSamuel.Tu@Sun.COM  * @vlan: the VLAN id to load
17039353SSamuel.Tu@Sun.COM  */
17049353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input * input,u16 * vlan)17059353SSamuel.Tu@Sun.COM ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan)
17069353SSamuel.Tu@Sun.COM {
170710998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_vlan_id_82599");
170810998SChenlu.Chen@Sun.COM 
17099353SSamuel.Tu@Sun.COM 	*vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET];
17109353SSamuel.Tu@Sun.COM 	*vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8;
17119353SSamuel.Tu@Sun.COM 
17129353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
17139353SSamuel.Tu@Sun.COM }
17149353SSamuel.Tu@Sun.COM 
17159353SSamuel.Tu@Sun.COM /*
17169353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_src_ipv4_82599 - Gets the source IPv4 address
17179353SSamuel.Tu@Sun.COM  * @input: input stream to search
17189353SSamuel.Tu@Sun.COM  * @src_addr: the IP address to load
17199353SSamuel.Tu@Sun.COM  */
17209353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input * input,u32 * src_addr)17219353SSamuel.Tu@Sun.COM ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr)
17229353SSamuel.Tu@Sun.COM {
172310998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_src_ipv4_82599");
172410998SChenlu.Chen@Sun.COM 
17259353SSamuel.Tu@Sun.COM 	*src_addr = input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET];
17269353SSamuel.Tu@Sun.COM 	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] << 8;
17279353SSamuel.Tu@Sun.COM 	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] << 16;
17289353SSamuel.Tu@Sun.COM 	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] << 24;
17299353SSamuel.Tu@Sun.COM 
17309353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
17319353SSamuel.Tu@Sun.COM }
17329353SSamuel.Tu@Sun.COM 
17339353SSamuel.Tu@Sun.COM /*
17349353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_dst_ipv4_82599 - Gets the destination IPv4 address
17359353SSamuel.Tu@Sun.COM  * @input: input stream to search
17369353SSamuel.Tu@Sun.COM  * @dst_addr: the IP address to load
17379353SSamuel.Tu@Sun.COM  */
17389353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input * input,u32 * dst_addr)17399353SSamuel.Tu@Sun.COM ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 *dst_addr)
17409353SSamuel.Tu@Sun.COM {
174110998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_dst_ipv4_82599");
174210998SChenlu.Chen@Sun.COM 
17439353SSamuel.Tu@Sun.COM 	*dst_addr = input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET];
17449353SSamuel.Tu@Sun.COM 	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] << 8;
17459353SSamuel.Tu@Sun.COM 	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] << 16;
17469353SSamuel.Tu@Sun.COM 	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] << 24;
17479353SSamuel.Tu@Sun.COM 
17489353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
17499353SSamuel.Tu@Sun.COM }
17509353SSamuel.Tu@Sun.COM 
17519353SSamuel.Tu@Sun.COM /*
17529353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_src_ipv6_82599 - Gets the source IPv6 address
17539353SSamuel.Tu@Sun.COM  * @input: input stream to search
17549353SSamuel.Tu@Sun.COM  * @src_addr_1: the first 4 bytes of the IP address to load
17559353SSamuel.Tu@Sun.COM  * @src_addr_2: the second 4 bytes of the IP address to load
17569353SSamuel.Tu@Sun.COM  * @src_addr_3: the third 4 bytes of the IP address to load
17579353SSamuel.Tu@Sun.COM  * @src_addr_4: the fourth 4 bytes of the IP address to load
17589353SSamuel.Tu@Sun.COM  */
17599353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input * input,u32 * src_addr_1,u32 * src_addr_2,u32 * src_addr_3,u32 * src_addr_4)17609353SSamuel.Tu@Sun.COM ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input,
17619353SSamuel.Tu@Sun.COM     u32 *src_addr_1, u32 *src_addr_2, u32 *src_addr_3, u32 *src_addr_4)
17629353SSamuel.Tu@Sun.COM {
176310998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_src_ipv6_82599");
176410998SChenlu.Chen@Sun.COM 
17659353SSamuel.Tu@Sun.COM 	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12];
17669353SSamuel.Tu@Sun.COM 	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] << 8;
17679353SSamuel.Tu@Sun.COM 	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] << 16;
17689353SSamuel.Tu@Sun.COM 	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] << 24;
17699353SSamuel.Tu@Sun.COM 
17709353SSamuel.Tu@Sun.COM 	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8];
17719353SSamuel.Tu@Sun.COM 	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] << 8;
17729353SSamuel.Tu@Sun.COM 	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] << 16;
17739353SSamuel.Tu@Sun.COM 	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] << 24;
17749353SSamuel.Tu@Sun.COM 
17759353SSamuel.Tu@Sun.COM 	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4];
17769353SSamuel.Tu@Sun.COM 	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] << 8;
17779353SSamuel.Tu@Sun.COM 	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] << 16;
17789353SSamuel.Tu@Sun.COM 	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] << 24;
17799353SSamuel.Tu@Sun.COM 
17809353SSamuel.Tu@Sun.COM 	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET];
17819353SSamuel.Tu@Sun.COM 	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] << 8;
17829353SSamuel.Tu@Sun.COM 	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] << 16;
17839353SSamuel.Tu@Sun.COM 	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] << 24;
17849353SSamuel.Tu@Sun.COM 
17859353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
17869353SSamuel.Tu@Sun.COM }
17879353SSamuel.Tu@Sun.COM 
17889353SSamuel.Tu@Sun.COM /*
17899353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_dst_ipv6_82599 - Gets the destination IPv6 address
17909353SSamuel.Tu@Sun.COM  * @input: input stream to search
17919353SSamuel.Tu@Sun.COM  * @dst_addr_1: the first 4 bytes of the IP address to load
17929353SSamuel.Tu@Sun.COM  * @dst_addr_2: the second 4 bytes of the IP address to load
17939353SSamuel.Tu@Sun.COM  * @dst_addr_3: the third 4 bytes of the IP address to load
17949353SSamuel.Tu@Sun.COM  * @dst_addr_4: the fourth 4 bytes of the IP address to load
17959353SSamuel.Tu@Sun.COM  */
17969353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input * input,u32 * dst_addr_1,u32 * dst_addr_2,u32 * dst_addr_3,u32 * dst_addr_4)17979353SSamuel.Tu@Sun.COM ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
17989353SSamuel.Tu@Sun.COM     u32 *dst_addr_1, u32 *dst_addr_2, u32 *dst_addr_3, u32 *dst_addr_4)
17999353SSamuel.Tu@Sun.COM {
180010998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_dst_ipv6_82599");
180110998SChenlu.Chen@Sun.COM 
18029353SSamuel.Tu@Sun.COM 	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12];
18039353SSamuel.Tu@Sun.COM 	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8;
18049353SSamuel.Tu@Sun.COM 	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16;
18059353SSamuel.Tu@Sun.COM 	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] << 24;
18069353SSamuel.Tu@Sun.COM 
18079353SSamuel.Tu@Sun.COM 	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8];
18089353SSamuel.Tu@Sun.COM 	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] << 8;
18099353SSamuel.Tu@Sun.COM 	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] << 16;
18109353SSamuel.Tu@Sun.COM 	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] << 24;
18119353SSamuel.Tu@Sun.COM 
18129353SSamuel.Tu@Sun.COM 	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4];
18139353SSamuel.Tu@Sun.COM 	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] << 8;
18149353SSamuel.Tu@Sun.COM 	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] << 16;
18159353SSamuel.Tu@Sun.COM 	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] << 24;
18169353SSamuel.Tu@Sun.COM 
18179353SSamuel.Tu@Sun.COM 	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET];
18189353SSamuel.Tu@Sun.COM 	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] << 8;
18199353SSamuel.Tu@Sun.COM 	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] << 16;
18209353SSamuel.Tu@Sun.COM 	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] << 24;
18219353SSamuel.Tu@Sun.COM 
18229353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
18239353SSamuel.Tu@Sun.COM }
18249353SSamuel.Tu@Sun.COM 
18259353SSamuel.Tu@Sun.COM /*
18269353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_src_port_82599 - Gets the source port
18279353SSamuel.Tu@Sun.COM  * @input: input stream to modify
18289353SSamuel.Tu@Sun.COM  * @src_port: the source port to load
18299353SSamuel.Tu@Sun.COM  *
18309353SSamuel.Tu@Sun.COM  * Even though the input is given in big-endian, the FDIRPORT registers
18319353SSamuel.Tu@Sun.COM  * expect the ports to be programmed in little-endian.  Hence the need to swap
18329353SSamuel.Tu@Sun.COM  * endianness when retrieving the data.  This can be confusing since the
18339353SSamuel.Tu@Sun.COM  * internal hash engine expects it to be big-endian.
18349353SSamuel.Tu@Sun.COM  */
18359353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input * input,u16 * src_port)18369353SSamuel.Tu@Sun.COM ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port)
18379353SSamuel.Tu@Sun.COM {
183810998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_src_port_82599");
183910998SChenlu.Chen@Sun.COM 
18409353SSamuel.Tu@Sun.COM 	*src_port = input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] << 8;
18419353SSamuel.Tu@Sun.COM 	*src_port |= input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1];
18429353SSamuel.Tu@Sun.COM 
18439353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
18449353SSamuel.Tu@Sun.COM }
18459353SSamuel.Tu@Sun.COM 
18469353SSamuel.Tu@Sun.COM /*
18479353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_dst_port_82599 - Gets the destination port
18489353SSamuel.Tu@Sun.COM  * @input: input stream to modify
18499353SSamuel.Tu@Sun.COM  * @dst_port: the destination port to load
18509353SSamuel.Tu@Sun.COM  *
18519353SSamuel.Tu@Sun.COM  * Even though the input is given in big-endian, the FDIRPORT registers
18529353SSamuel.Tu@Sun.COM  * expect the ports to be programmed in little-endian.  Hence the need to swap
18539353SSamuel.Tu@Sun.COM  * endianness when retrieving the data.  This can be confusing since the
18549353SSamuel.Tu@Sun.COM  * internal hash engine expects it to be big-endian.
18559353SSamuel.Tu@Sun.COM  */
18569353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input * input,u16 * dst_port)18579353SSamuel.Tu@Sun.COM ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port)
18589353SSamuel.Tu@Sun.COM {
185910998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_dst_port_82599");
186010998SChenlu.Chen@Sun.COM 
18619353SSamuel.Tu@Sun.COM 	*dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8;
18629353SSamuel.Tu@Sun.COM 	*dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1];
18639353SSamuel.Tu@Sun.COM 
18649353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
18659353SSamuel.Tu@Sun.COM }
18669353SSamuel.Tu@Sun.COM 
18679353SSamuel.Tu@Sun.COM /*
18689353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_flex_byte_82599 - Gets the flexible bytes
18699353SSamuel.Tu@Sun.COM  * @input: input stream to modify
18709353SSamuel.Tu@Sun.COM  * @flex_bytes: the flexible bytes to load
18719353SSamuel.Tu@Sun.COM  */
18729353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input * input,u16 * flex_byte)18739353SSamuel.Tu@Sun.COM ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte)
18749353SSamuel.Tu@Sun.COM {
187510998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_flex_byte_82599");
187610998SChenlu.Chen@Sun.COM 
18779353SSamuel.Tu@Sun.COM 	*flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET];
18789353SSamuel.Tu@Sun.COM 	*flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8;
18799353SSamuel.Tu@Sun.COM 
18809353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
18819353SSamuel.Tu@Sun.COM }
18829353SSamuel.Tu@Sun.COM 
18839353SSamuel.Tu@Sun.COM /*
18849353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_vm_pool_82599 - Gets the Virtual Machine pool
18859353SSamuel.Tu@Sun.COM  * @input: input stream to modify
18869353SSamuel.Tu@Sun.COM  * @vm_pool: the Virtual Machine pool to load
18879353SSamuel.Tu@Sun.COM  */
18889353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input * input,u8 * vm_pool)18899353SSamuel.Tu@Sun.COM ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool)
18909353SSamuel.Tu@Sun.COM {
189110998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_vm_pool_82599");
189210998SChenlu.Chen@Sun.COM 
18939353SSamuel.Tu@Sun.COM 	*vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET];
18949353SSamuel.Tu@Sun.COM 
18959353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
18969353SSamuel.Tu@Sun.COM }
18979353SSamuel.Tu@Sun.COM 
18989353SSamuel.Tu@Sun.COM /*
18999353SSamuel.Tu@Sun.COM  * ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type
19009353SSamuel.Tu@Sun.COM  * @input: input stream to modify
19019353SSamuel.Tu@Sun.COM  * @l4type: the layer 4 type value to load
19029353SSamuel.Tu@Sun.COM  */
19039353SSamuel.Tu@Sun.COM s32
ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input * input,u8 * l4type)19049353SSamuel.Tu@Sun.COM ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, u8 *l4type)
19059353SSamuel.Tu@Sun.COM {
190610998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_atr_get_l4type__82599");
190710998SChenlu.Chen@Sun.COM 
19089353SSamuel.Tu@Sun.COM 	*l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET];
19099353SSamuel.Tu@Sun.COM 
19109353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
19119353SSamuel.Tu@Sun.COM }
19129353SSamuel.Tu@Sun.COM 
19139353SSamuel.Tu@Sun.COM /*
19149353SSamuel.Tu@Sun.COM  * ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter
19159353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
19169353SSamuel.Tu@Sun.COM  * @stream: input bitstream
19179353SSamuel.Tu@Sun.COM  * @queue: queue index to direct traffic to
19189353SSamuel.Tu@Sun.COM  */
19199353SSamuel.Tu@Sun.COM s32
ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw * hw,struct ixgbe_atr_input * input,u8 queue)19209353SSamuel.Tu@Sun.COM ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
19219353SSamuel.Tu@Sun.COM     struct ixgbe_atr_input *input, u8 queue)
19229353SSamuel.Tu@Sun.COM {
19239353SSamuel.Tu@Sun.COM 	u64  fdirhashcmd;
19249353SSamuel.Tu@Sun.COM 	u64  fdircmd;
19259353SSamuel.Tu@Sun.COM 	u32  fdirhash;
19269353SSamuel.Tu@Sun.COM 	u16  bucket_hash, sig_hash;
19279353SSamuel.Tu@Sun.COM 	u8   l4type;
19289353SSamuel.Tu@Sun.COM 
192910998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
193010998SChenlu.Chen@Sun.COM 
19319353SSamuel.Tu@Sun.COM 	bucket_hash = ixgbe_atr_compute_hash_82599(input,
19329353SSamuel.Tu@Sun.COM 	    IXGBE_ATR_BUCKET_HASH_KEY);
19339353SSamuel.Tu@Sun.COM 
19349353SSamuel.Tu@Sun.COM 	/* bucket_hash is only 15 bits */
19359353SSamuel.Tu@Sun.COM 	bucket_hash &= IXGBE_ATR_HASH_MASK;
19369353SSamuel.Tu@Sun.COM 
19379353SSamuel.Tu@Sun.COM 	sig_hash = ixgbe_atr_compute_hash_82599(input,
19389353SSamuel.Tu@Sun.COM 	    IXGBE_ATR_SIGNATURE_HASH_KEY);
19399353SSamuel.Tu@Sun.COM 
19409353SSamuel.Tu@Sun.COM 	/* Get the l4type in order to program FDIRCMD properly */
19419353SSamuel.Tu@Sun.COM 	/* lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 */
19429353SSamuel.Tu@Sun.COM 	(void) ixgbe_atr_get_l4type_82599(input, &l4type);
19439353SSamuel.Tu@Sun.COM 
19449353SSamuel.Tu@Sun.COM 	/*
19459353SSamuel.Tu@Sun.COM 	 * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
19469353SSamuel.Tu@Sun.COM 	 * is for FDIRCMD.  Then do a 64-bit register write from FDIRHASH.
19479353SSamuel.Tu@Sun.COM 	 */
19489353SSamuel.Tu@Sun.COM 	fdirhash = sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
19499353SSamuel.Tu@Sun.COM 
19509353SSamuel.Tu@Sun.COM 	fdircmd = (IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
19519353SSamuel.Tu@Sun.COM 	    IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN);
19529353SSamuel.Tu@Sun.COM 
19539353SSamuel.Tu@Sun.COM 	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
19549353SSamuel.Tu@Sun.COM 	case IXGBE_ATR_L4TYPE_TCP:
19559353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
19569353SSamuel.Tu@Sun.COM 		break;
19579353SSamuel.Tu@Sun.COM 	case IXGBE_ATR_L4TYPE_UDP:
19589353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
19599353SSamuel.Tu@Sun.COM 		break;
19609353SSamuel.Tu@Sun.COM 	case IXGBE_ATR_L4TYPE_SCTP:
19619353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
19629353SSamuel.Tu@Sun.COM 		break;
19639353SSamuel.Tu@Sun.COM 	default:
19649353SSamuel.Tu@Sun.COM 		DEBUGOUT(" Error on l4type input\n");
19659353SSamuel.Tu@Sun.COM 		return (IXGBE_ERR_CONFIG);
19669353SSamuel.Tu@Sun.COM 	}
19679353SSamuel.Tu@Sun.COM 
19689353SSamuel.Tu@Sun.COM 	if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK)
19699353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_IPV6;
19709353SSamuel.Tu@Sun.COM 
19719353SSamuel.Tu@Sun.COM 	fdircmd |= ((u64)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT);
19729353SSamuel.Tu@Sun.COM 	fdirhashcmd = ((fdircmd << 32) | fdirhash);
19739353SSamuel.Tu@Sun.COM 
19749353SSamuel.Tu@Sun.COM 	DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, fdirhash & 0x7FFF7FFF);
19759353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
19769353SSamuel.Tu@Sun.COM 
19779353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
19789353SSamuel.Tu@Sun.COM }
19799353SSamuel.Tu@Sun.COM 
19809353SSamuel.Tu@Sun.COM /*
19819353SSamuel.Tu@Sun.COM  * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
19829353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
19839353SSamuel.Tu@Sun.COM  * @input: input bitstream
1984*13006SChenlu.Chen@Sun.COM  * @input_masks: masks for the input bitstream
1985*13006SChenlu.Chen@Sun.COM  * @soft_id: software index for the filters
19869353SSamuel.Tu@Sun.COM  * @queue: queue index to direct traffic to
19879353SSamuel.Tu@Sun.COM  *
19889353SSamuel.Tu@Sun.COM  * Note that the caller to this function must lock before calling, since the
19899353SSamuel.Tu@Sun.COM  * hardware writes must be protected from one another.
19909353SSamuel.Tu@Sun.COM  */
19919353SSamuel.Tu@Sun.COM s32
ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw * hw,struct ixgbe_atr_input * input,struct ixgbe_atr_input_masks * input_masks,u16 soft_id,u8 queue)19929353SSamuel.Tu@Sun.COM ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
1993*13006SChenlu.Chen@Sun.COM     struct ixgbe_atr_input *input, struct ixgbe_atr_input_masks *input_masks,
1994*13006SChenlu.Chen@Sun.COM     u16 soft_id, u8 queue)
19959353SSamuel.Tu@Sun.COM {
19969353SSamuel.Tu@Sun.COM 	u32 fdircmd = 0;
19979353SSamuel.Tu@Sun.COM 	u32 fdirhash;
1998*13006SChenlu.Chen@Sun.COM 	u32 src_ipv4 = 0, dst_ipv4 = 0;
19999353SSamuel.Tu@Sun.COM 	u32 src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4;
20009353SSamuel.Tu@Sun.COM 	u16 src_port, dst_port, vlan_id, flex_bytes;
20019353SSamuel.Tu@Sun.COM 	u16 bucket_hash;
20029353SSamuel.Tu@Sun.COM 	u8  l4type;
2003*13006SChenlu.Chen@Sun.COM 	u8  fdirm = 0;
20049353SSamuel.Tu@Sun.COM 
200510998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599");
200610998SChenlu.Chen@Sun.COM 
20079353SSamuel.Tu@Sun.COM 	/* Get our input values */
20089353SSamuel.Tu@Sun.COM 	(void) ixgbe_atr_get_l4type_82599(input, &l4type);
20099353SSamuel.Tu@Sun.COM 
20109353SSamuel.Tu@Sun.COM 	/*
20119353SSamuel.Tu@Sun.COM 	 * Check l4type formatting, and bail out before we touch the hardware
20129353SSamuel.Tu@Sun.COM 	 * if there's a configuration issue
20139353SSamuel.Tu@Sun.COM 	 */
20149353SSamuel.Tu@Sun.COM 	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
20159353SSamuel.Tu@Sun.COM 	case IXGBE_ATR_L4TYPE_TCP:
20169353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
20179353SSamuel.Tu@Sun.COM 		break;
20189353SSamuel.Tu@Sun.COM 	case IXGBE_ATR_L4TYPE_UDP:
20199353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
20209353SSamuel.Tu@Sun.COM 		break;
20219353SSamuel.Tu@Sun.COM 	case IXGBE_ATR_L4TYPE_SCTP:
20229353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
20239353SSamuel.Tu@Sun.COM 		break;
20249353SSamuel.Tu@Sun.COM 	default:
20259353SSamuel.Tu@Sun.COM 		DEBUGOUT(" Error on l4type input\n");
20269353SSamuel.Tu@Sun.COM 		return (IXGBE_ERR_CONFIG);
20279353SSamuel.Tu@Sun.COM 	}
20289353SSamuel.Tu@Sun.COM 
20299353SSamuel.Tu@Sun.COM 	bucket_hash = ixgbe_atr_compute_hash_82599(input,
20309353SSamuel.Tu@Sun.COM 	    IXGBE_ATR_BUCKET_HASH_KEY);
20319353SSamuel.Tu@Sun.COM 
20329353SSamuel.Tu@Sun.COM 	/* bucket_hash is only 15 bits */
20339353SSamuel.Tu@Sun.COM 	bucket_hash &= IXGBE_ATR_HASH_MASK;
20349353SSamuel.Tu@Sun.COM 
20359353SSamuel.Tu@Sun.COM 	(void) ixgbe_atr_get_vlan_id_82599(input, &vlan_id);
20369353SSamuel.Tu@Sun.COM 	(void) ixgbe_atr_get_src_port_82599(input, &src_port);
20379353SSamuel.Tu@Sun.COM 	(void) ixgbe_atr_get_dst_port_82599(input, &dst_port);
20389353SSamuel.Tu@Sun.COM 	(void) ixgbe_atr_get_flex_byte_82599(input, &flex_bytes);
20399353SSamuel.Tu@Sun.COM 
20409353SSamuel.Tu@Sun.COM 	fdirhash = soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
20419353SSamuel.Tu@Sun.COM 
20429353SSamuel.Tu@Sun.COM 	/* Now figure out if we're IPv4 or IPv6 */
20439353SSamuel.Tu@Sun.COM 	if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK) {
20449353SSamuel.Tu@Sun.COM 		/* IPv6 */
20459353SSamuel.Tu@Sun.COM 		(void) ixgbe_atr_get_src_ipv6_82599(input, &src_ipv6_1,
20469353SSamuel.Tu@Sun.COM 		    &src_ipv6_2, &src_ipv6_3, &src_ipv6_4);
20479353SSamuel.Tu@Sun.COM 
20489353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), src_ipv6_1);
20499353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), src_ipv6_2);
20509353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), src_ipv6_3);
20519353SSamuel.Tu@Sun.COM 		/* The last 4 bytes is the same register as IPv4 */
20529353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv6_4);
20539353SSamuel.Tu@Sun.COM 
20549353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_IPV6;
20559353SSamuel.Tu@Sun.COM 		fdircmd |= IXGBE_FDIRCMD_IPv6DMATCH;
20569353SSamuel.Tu@Sun.COM 	} else {
20579353SSamuel.Tu@Sun.COM 		/* IPv4 */
20589353SSamuel.Tu@Sun.COM 		(void) ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4);
20599353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4);
20609353SSamuel.Tu@Sun.COM 
20619353SSamuel.Tu@Sun.COM 	}
20629353SSamuel.Tu@Sun.COM 
20639353SSamuel.Tu@Sun.COM 	(void) ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4);
20649353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, dst_ipv4);
20659353SSamuel.Tu@Sun.COM 
20669353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id |
20679353SSamuel.Tu@Sun.COM 	    (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT)));
20689353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port |
20699353SSamuel.Tu@Sun.COM 	    (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
20709353SSamuel.Tu@Sun.COM 
2071*13006SChenlu.Chen@Sun.COM 	/*
2072*13006SChenlu.Chen@Sun.COM 	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
2073*13006SChenlu.Chen@Sun.COM 	 * are zero, then assume a full mask for that field.  Also assume that
2074*13006SChenlu.Chen@Sun.COM 	 * a VLAN of 0 is unspecified, so mask that out as well.  L4type
2075*13006SChenlu.Chen@Sun.COM 	 * cannot be masked out in this implementation.
2076*13006SChenlu.Chen@Sun.COM 	 *
2077*13006SChenlu.Chen@Sun.COM 	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
2078*13006SChenlu.Chen@Sun.COM 	 * point in time.
2079*13006SChenlu.Chen@Sun.COM 	 */
2080*13006SChenlu.Chen@Sun.COM 	if (src_ipv4 == 0)
2081*13006SChenlu.Chen@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff);
2082*13006SChenlu.Chen@Sun.COM 	else
2083*13006SChenlu.Chen@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);
2084*13006SChenlu.Chen@Sun.COM 
2085*13006SChenlu.Chen@Sun.COM 	if (dst_ipv4 == 0)
2086*13006SChenlu.Chen@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xffffffff);
2087*13006SChenlu.Chen@Sun.COM 	else
2088*13006SChenlu.Chen@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
2089*13006SChenlu.Chen@Sun.COM 
2090*13006SChenlu.Chen@Sun.COM 	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
2091*13006SChenlu.Chen@Sun.COM 	case IXGBE_ATR_L4TYPE_TCP:
2092*13006SChenlu.Chen@Sun.COM 		if (src_port == 0)
2093*13006SChenlu.Chen@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xffff);
2094*13006SChenlu.Chen@Sun.COM 		else
2095*13006SChenlu.Chen@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
2096*13006SChenlu.Chen@Sun.COM 			    input_masks->src_port_mask);
2097*13006SChenlu.Chen@Sun.COM 
2098*13006SChenlu.Chen@Sun.COM 		if (dst_port == 0)
2099*13006SChenlu.Chen@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
2100*13006SChenlu.Chen@Sun.COM 			    (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
2101*13006SChenlu.Chen@Sun.COM 			    0xffff0000));
2102*13006SChenlu.Chen@Sun.COM 		else
2103*13006SChenlu.Chen@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
2104*13006SChenlu.Chen@Sun.COM 			    (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
2105*13006SChenlu.Chen@Sun.COM 			    (input_masks->dst_port_mask << 16)));
2106*13006SChenlu.Chen@Sun.COM 		break;
2107*13006SChenlu.Chen@Sun.COM 	case IXGBE_ATR_L4TYPE_UDP:
2108*13006SChenlu.Chen@Sun.COM 		if (src_port == 0)
2109*13006SChenlu.Chen@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xffff);
2110*13006SChenlu.Chen@Sun.COM 		else
2111*13006SChenlu.Chen@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
2112*13006SChenlu.Chen@Sun.COM 			    input_masks->src_port_mask);
2113*13006SChenlu.Chen@Sun.COM 
2114*13006SChenlu.Chen@Sun.COM 		if (dst_port == 0)
2115*13006SChenlu.Chen@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
2116*13006SChenlu.Chen@Sun.COM 			    (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
2117*13006SChenlu.Chen@Sun.COM 			    0xffff0000));
2118*13006SChenlu.Chen@Sun.COM 		else
2119*13006SChenlu.Chen@Sun.COM 			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
2120*13006SChenlu.Chen@Sun.COM 			    (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
2121*13006SChenlu.Chen@Sun.COM 			    (input_masks->src_port_mask << 16)));
2122*13006SChenlu.Chen@Sun.COM 		break;
2123*13006SChenlu.Chen@Sun.COM 	default:
2124*13006SChenlu.Chen@Sun.COM 		/* this already would have failed above */
2125*13006SChenlu.Chen@Sun.COM 		break;
2126*13006SChenlu.Chen@Sun.COM 	}
2127*13006SChenlu.Chen@Sun.COM 
2128*13006SChenlu.Chen@Sun.COM 	/* Program the last mask register, FDIRM */
2129*13006SChenlu.Chen@Sun.COM 	if (input_masks->vlan_id_mask || !vlan_id)
2130*13006SChenlu.Chen@Sun.COM 		/* Mask both VLAN and VLANP - bits 0 and 1 */
2131*13006SChenlu.Chen@Sun.COM 		fdirm |= (IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP);
2132*13006SChenlu.Chen@Sun.COM 
2133*13006SChenlu.Chen@Sun.COM 	if (input_masks->data_mask || !flex_bytes)
2134*13006SChenlu.Chen@Sun.COM 		/* Flex bytes need masking, so mask the whole thing - bit 4 */
2135*13006SChenlu.Chen@Sun.COM 		fdirm |= IXGBE_FDIRM_FLEX;
2136*13006SChenlu.Chen@Sun.COM 
2137*13006SChenlu.Chen@Sun.COM 	/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
2138*13006SChenlu.Chen@Sun.COM 	fdirm |= (IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6);
2139*13006SChenlu.Chen@Sun.COM 
2140*13006SChenlu.Chen@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
2141*13006SChenlu.Chen@Sun.COM 
21429353SSamuel.Tu@Sun.COM 	fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW;
21439353SSamuel.Tu@Sun.COM 	fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE;
21449353SSamuel.Tu@Sun.COM 	fdircmd |= IXGBE_FDIRCMD_LAST;
21459353SSamuel.Tu@Sun.COM 	fdircmd |= IXGBE_FDIRCMD_QUEUE_EN;
21469353SSamuel.Tu@Sun.COM 	fdircmd |= queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
21479353SSamuel.Tu@Sun.COM 
21489353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
21499353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
21509353SSamuel.Tu@Sun.COM 
21519353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
21529353SSamuel.Tu@Sun.COM }
21539353SSamuel.Tu@Sun.COM 
21549353SSamuel.Tu@Sun.COM /*
21559353SSamuel.Tu@Sun.COM  * ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
21569353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
21579353SSamuel.Tu@Sun.COM  * @reg: analog register to read
21589353SSamuel.Tu@Sun.COM  * @val: read value
21599353SSamuel.Tu@Sun.COM  *
21609353SSamuel.Tu@Sun.COM  * Performs read operation to Omer analog register specified.
21619353SSamuel.Tu@Sun.COM  */
21629353SSamuel.Tu@Sun.COM s32
ixgbe_read_analog_reg8_82599(struct ixgbe_hw * hw,u32 reg,u8 * val)21639353SSamuel.Tu@Sun.COM ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val)
21649353SSamuel.Tu@Sun.COM {
21659353SSamuel.Tu@Sun.COM 	u32  core_ctl;
21669353SSamuel.Tu@Sun.COM 
216710998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_read_analog_reg8_82599");
216810998SChenlu.Chen@Sun.COM 
21699353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD |
21709353SSamuel.Tu@Sun.COM 	    (reg << 8));
21719353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
21729353SSamuel.Tu@Sun.COM 	usec_delay(10);
21739353SSamuel.Tu@Sun.COM 	core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL);
21749353SSamuel.Tu@Sun.COM 	*val = (u8)core_ctl;
21759353SSamuel.Tu@Sun.COM 
21769353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
21779353SSamuel.Tu@Sun.COM }
21789353SSamuel.Tu@Sun.COM 
21799353SSamuel.Tu@Sun.COM /*
21809353SSamuel.Tu@Sun.COM  * ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register
21819353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
21829353SSamuel.Tu@Sun.COM  * @reg: atlas register to write
21839353SSamuel.Tu@Sun.COM  * @val: value to write
21849353SSamuel.Tu@Sun.COM  *
21859353SSamuel.Tu@Sun.COM  * Performs write operation to Omer analog register specified.
21869353SSamuel.Tu@Sun.COM  */
21879353SSamuel.Tu@Sun.COM s32
ixgbe_write_analog_reg8_82599(struct ixgbe_hw * hw,u32 reg,u8 val)21889353SSamuel.Tu@Sun.COM ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val)
21899353SSamuel.Tu@Sun.COM {
21909353SSamuel.Tu@Sun.COM 	u32  core_ctl;
21919353SSamuel.Tu@Sun.COM 
219210998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_write_analog_reg8_82599");
219310998SChenlu.Chen@Sun.COM 
21949353SSamuel.Tu@Sun.COM 	core_ctl = (reg << 8) | val;
21959353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl);
21969353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
21979353SSamuel.Tu@Sun.COM 	usec_delay(10);
21989353SSamuel.Tu@Sun.COM 
21999353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
22009353SSamuel.Tu@Sun.COM }
22019353SSamuel.Tu@Sun.COM 
22029353SSamuel.Tu@Sun.COM /*
22039353SSamuel.Tu@Sun.COM  * ixgbe_start_hw_rev_1_82599 - Prepare hardware for Tx/Rx
22049353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
22059353SSamuel.Tu@Sun.COM  *
22069353SSamuel.Tu@Sun.COM  * Starts the hardware using the generic start_hw function.
22079353SSamuel.Tu@Sun.COM  * Then performs revision-specific operations:
22089353SSamuel.Tu@Sun.COM  * Clears the rate limiter registers.
22099353SSamuel.Tu@Sun.COM  */
22109353SSamuel.Tu@Sun.COM s32
ixgbe_start_hw_rev_1_82599(struct ixgbe_hw * hw)22119353SSamuel.Tu@Sun.COM ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw)
22129353SSamuel.Tu@Sun.COM {
221310998SChenlu.Chen@Sun.COM 	u32 i;
221412003SPaul.Guo@Sun.COM 	u32 regval;
22159353SSamuel.Tu@Sun.COM 	s32 ret_val = IXGBE_SUCCESS;
22169353SSamuel.Tu@Sun.COM 
221710998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_start_hw_rev_1__82599");
221810998SChenlu.Chen@Sun.COM 
22199353SSamuel.Tu@Sun.COM 	ret_val = ixgbe_start_hw_generic(hw);
22209353SSamuel.Tu@Sun.COM 
22219353SSamuel.Tu@Sun.COM 	/* Clear the rate limiters */
222210998SChenlu.Chen@Sun.COM 	for (i = 0; i < hw->mac.max_tx_queues; i++) {
222310998SChenlu.Chen@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i);
22249353SSamuel.Tu@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0);
22259353SSamuel.Tu@Sun.COM 	}
22269353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
22279353SSamuel.Tu@Sun.COM 
222812003SPaul.Guo@Sun.COM 	/* Disable relaxed ordering */
222912003SPaul.Guo@Sun.COM 	for (i = 0; i < hw->mac.max_tx_queues; i++) {
223012003SPaul.Guo@Sun.COM 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
223112003SPaul.Guo@Sun.COM 		regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
223212003SPaul.Guo@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
223312003SPaul.Guo@Sun.COM 	}
223412003SPaul.Guo@Sun.COM 
223512003SPaul.Guo@Sun.COM 	for (i = 0; i < hw->mac.max_rx_queues; i++) {
223612003SPaul.Guo@Sun.COM 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
223712003SPaul.Guo@Sun.COM 		regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
223812003SPaul.Guo@Sun.COM 		    IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
223912003SPaul.Guo@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
224012003SPaul.Guo@Sun.COM 	}
224112003SPaul.Guo@Sun.COM 
224210305SPaul.Guo@Sun.COM 	/* We need to run link autotry after the driver loads */
224310305SPaul.Guo@Sun.COM 	hw->mac.autotry_restart = true;
224410305SPaul.Guo@Sun.COM 
224510305SPaul.Guo@Sun.COM 	if (ret_val == IXGBE_SUCCESS)
224610305SPaul.Guo@Sun.COM 		ret_val = ixgbe_verify_fw_version_82599(hw);
224710305SPaul.Guo@Sun.COM 
22489353SSamuel.Tu@Sun.COM 	return (ret_val);
22499353SSamuel.Tu@Sun.COM }
22509353SSamuel.Tu@Sun.COM 
22519353SSamuel.Tu@Sun.COM /*
22529353SSamuel.Tu@Sun.COM  * ixgbe_identify_phy_82599 - Get physical layer module
22539353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
22549353SSamuel.Tu@Sun.COM  *
22559353SSamuel.Tu@Sun.COM  * Determines the physical layer module found on the current adapter.
22569353SSamuel.Tu@Sun.COM  * If PHY already detected, maintains current PHY type in hw struct,
22579353SSamuel.Tu@Sun.COM  * otherwise executes the PHY detection routine.
22589353SSamuel.Tu@Sun.COM  */
22599353SSamuel.Tu@Sun.COM s32
ixgbe_identify_phy_82599(struct ixgbe_hw * hw)22609353SSamuel.Tu@Sun.COM ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
22619353SSamuel.Tu@Sun.COM {
22629353SSamuel.Tu@Sun.COM 	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
22639353SSamuel.Tu@Sun.COM 
226410998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_identify_phy_82599");
226510998SChenlu.Chen@Sun.COM 
22669353SSamuel.Tu@Sun.COM 	/* Detect PHY if not unknown - returns success if already detected. */
22679353SSamuel.Tu@Sun.COM 	status = ixgbe_identify_phy_generic(hw);
22689353SSamuel.Tu@Sun.COM 	if (status != IXGBE_SUCCESS)
22699353SSamuel.Tu@Sun.COM 		status = ixgbe_identify_sfp_module_generic(hw);
22709353SSamuel.Tu@Sun.COM 	/* Set PHY type none if no PHY detected */
22719353SSamuel.Tu@Sun.COM 	if (hw->phy.type == ixgbe_phy_unknown) {
22729353SSamuel.Tu@Sun.COM 		hw->phy.type = ixgbe_phy_none;
22739353SSamuel.Tu@Sun.COM 		status = IXGBE_SUCCESS;
22749353SSamuel.Tu@Sun.COM 	}
22759353SSamuel.Tu@Sun.COM 
22769353SSamuel.Tu@Sun.COM 	/* Return error if SFP module has been detected but is not supported */
22779353SSamuel.Tu@Sun.COM 	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
22789353SSamuel.Tu@Sun.COM 		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
22799353SSamuel.Tu@Sun.COM 
22809353SSamuel.Tu@Sun.COM 	return (status);
22819353SSamuel.Tu@Sun.COM }
22829353SSamuel.Tu@Sun.COM 
22839353SSamuel.Tu@Sun.COM /*
22849353SSamuel.Tu@Sun.COM  * ixgbe_get_supported_physical_layer_82599 - Returns physical layer type
22859353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
22869353SSamuel.Tu@Sun.COM  *
22879353SSamuel.Tu@Sun.COM  * Determines physical layer capabilities of the current configuration.
22889353SSamuel.Tu@Sun.COM  */
22899353SSamuel.Tu@Sun.COM u32
ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw * hw)22909353SSamuel.Tu@Sun.COM ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
22919353SSamuel.Tu@Sun.COM {
22929353SSamuel.Tu@Sun.COM 	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
22939353SSamuel.Tu@Sun.COM 	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
22949353SSamuel.Tu@Sun.COM 	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
22959353SSamuel.Tu@Sun.COM 	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
22969353SSamuel.Tu@Sun.COM 	u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
22979353SSamuel.Tu@Sun.COM 	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
22989353SSamuel.Tu@Sun.COM 	u16 ext_ability = 0;
22999353SSamuel.Tu@Sun.COM 	u8 comp_codes_10g = 0;
2300*13006SChenlu.Chen@Sun.COM 	u8 comp_codes_1g = 0;
23019353SSamuel.Tu@Sun.COM 
230210998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_get_support_physical_layer_82599");
230310998SChenlu.Chen@Sun.COM 
23049353SSamuel.Tu@Sun.COM 	hw->phy.ops.identify(hw);
23059353SSamuel.Tu@Sun.COM 
23069353SSamuel.Tu@Sun.COM 	if (hw->phy.type == ixgbe_phy_tn ||
230710998SChenlu.Chen@Sun.COM 	    hw->phy.type == ixgbe_phy_aq ||
23089353SSamuel.Tu@Sun.COM 	    hw->phy.type == ixgbe_phy_cu_unknown) {
23099353SSamuel.Tu@Sun.COM 		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
23109353SSamuel.Tu@Sun.COM 		    IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
23119353SSamuel.Tu@Sun.COM 		if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
23129353SSamuel.Tu@Sun.COM 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
23139353SSamuel.Tu@Sun.COM 		if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
23149353SSamuel.Tu@Sun.COM 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
23159353SSamuel.Tu@Sun.COM 		if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
23169353SSamuel.Tu@Sun.COM 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
23179353SSamuel.Tu@Sun.COM 		goto out;
23189353SSamuel.Tu@Sun.COM 	}
23199353SSamuel.Tu@Sun.COM 
23209353SSamuel.Tu@Sun.COM 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
23219353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_1G_AN:
23229353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
23239353SSamuel.Tu@Sun.COM 		if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) {
23249353SSamuel.Tu@Sun.COM 			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
23259353SSamuel.Tu@Sun.COM 			    IXGBE_PHYSICAL_LAYER_1000BASE_BX;
23269353SSamuel.Tu@Sun.COM 			goto out;
232710305SPaul.Guo@Sun.COM 		} else {
23289353SSamuel.Tu@Sun.COM 			/* SFI mode so read SFP module */
23299353SSamuel.Tu@Sun.COM 			goto sfp_check;
233010305SPaul.Guo@Sun.COM 		}
23319353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
23329353SSamuel.Tu@Sun.COM 		if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4)
23339353SSamuel.Tu@Sun.COM 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
23349353SSamuel.Tu@Sun.COM 		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4)
23359353SSamuel.Tu@Sun.COM 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
233610305SPaul.Guo@Sun.COM 		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI)
233710305SPaul.Guo@Sun.COM 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI;
23389353SSamuel.Tu@Sun.COM 		goto out;
23399353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_10G_SERIAL:
23409353SSamuel.Tu@Sun.COM 		if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) {
23419353SSamuel.Tu@Sun.COM 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR;
23429353SSamuel.Tu@Sun.COM 			goto out;
23439353SSamuel.Tu@Sun.COM 		} else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)
23449353SSamuel.Tu@Sun.COM 			goto sfp_check;
23459353SSamuel.Tu@Sun.COM 		break;
23469353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
23479353SSamuel.Tu@Sun.COM 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
23489353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KX_SUPP)
23499353SSamuel.Tu@Sun.COM 			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
23509353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KX4_SUPP)
23519353SSamuel.Tu@Sun.COM 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
23529353SSamuel.Tu@Sun.COM 		if (autoc & IXGBE_AUTOC_KR_SUPP)
23539353SSamuel.Tu@Sun.COM 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
23549353SSamuel.Tu@Sun.COM 		goto out;
23559353SSamuel.Tu@Sun.COM 	default:
23569353SSamuel.Tu@Sun.COM 		goto out;
23579353SSamuel.Tu@Sun.COM 	}
23589353SSamuel.Tu@Sun.COM 
23599353SSamuel.Tu@Sun.COM sfp_check:
23609353SSamuel.Tu@Sun.COM 	/*
23619353SSamuel.Tu@Sun.COM 	 * SFP check must be done last since DA modules are sometimes used to
23629353SSamuel.Tu@Sun.COM 	 * test KR mode -  we need to id KR mode correctly before SFP module.
23639353SSamuel.Tu@Sun.COM 	 * Call identify_sfp because the pluggable module may have changed
23649353SSamuel.Tu@Sun.COM 	 */
23659353SSamuel.Tu@Sun.COM 	hw->phy.ops.identify_sfp(hw);
23669353SSamuel.Tu@Sun.COM 	if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
23679353SSamuel.Tu@Sun.COM 		goto out;
23689353SSamuel.Tu@Sun.COM 
23699353SSamuel.Tu@Sun.COM 	switch (hw->phy.type) {
2370*13006SChenlu.Chen@Sun.COM 	case ixgbe_phy_sfp_passive_tyco:
2371*13006SChenlu.Chen@Sun.COM 	case ixgbe_phy_sfp_passive_unknown:
23729353SSamuel.Tu@Sun.COM 		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
23739353SSamuel.Tu@Sun.COM 		break;
2374*13006SChenlu.Chen@Sun.COM 	case ixgbe_phy_sfp_ftl_active:
2375*13006SChenlu.Chen@Sun.COM 	case ixgbe_phy_sfp_active_unknown:
2376*13006SChenlu.Chen@Sun.COM 		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
2377*13006SChenlu.Chen@Sun.COM 		break;
23789353SSamuel.Tu@Sun.COM 	case ixgbe_phy_sfp_avago:
23799353SSamuel.Tu@Sun.COM 	case ixgbe_phy_sfp_ftl:
23809353SSamuel.Tu@Sun.COM 	case ixgbe_phy_sfp_intel:
23819353SSamuel.Tu@Sun.COM 	case ixgbe_phy_sfp_unknown:
23829353SSamuel.Tu@Sun.COM 		hw->phy.ops.read_i2c_eeprom(hw,
2383*13006SChenlu.Chen@Sun.COM 		    IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g);
2384*13006SChenlu.Chen@Sun.COM 		hw->phy.ops.read_i2c_eeprom(hw,
23859353SSamuel.Tu@Sun.COM 		    IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g);
23869353SSamuel.Tu@Sun.COM 		if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
23879353SSamuel.Tu@Sun.COM 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
23889353SSamuel.Tu@Sun.COM 		else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
23899353SSamuel.Tu@Sun.COM 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
2390*13006SChenlu.Chen@Sun.COM 		else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
2391*13006SChenlu.Chen@Sun.COM 			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T;
23929353SSamuel.Tu@Sun.COM 		break;
23939353SSamuel.Tu@Sun.COM 	default:
23949353SSamuel.Tu@Sun.COM 		break;
23959353SSamuel.Tu@Sun.COM 	}
23969353SSamuel.Tu@Sun.COM 
23979353SSamuel.Tu@Sun.COM out:
23989353SSamuel.Tu@Sun.COM 	return (physical_layer);
23999353SSamuel.Tu@Sun.COM }
24009353SSamuel.Tu@Sun.COM 
24019353SSamuel.Tu@Sun.COM /*
24029353SSamuel.Tu@Sun.COM  * ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599
24039353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
24049353SSamuel.Tu@Sun.COM  * @regval: register value to write to RXCTRL
24059353SSamuel.Tu@Sun.COM  *
24069353SSamuel.Tu@Sun.COM  * Enables the Rx DMA unit for 82599
24079353SSamuel.Tu@Sun.COM  */
24089353SSamuel.Tu@Sun.COM s32
ixgbe_enable_rx_dma_82599(struct ixgbe_hw * hw,u32 regval)24099353SSamuel.Tu@Sun.COM ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
24109353SSamuel.Tu@Sun.COM {
24119353SSamuel.Tu@Sun.COM #define	IXGBE_MAX_SECRX_POLL	30
24129353SSamuel.Tu@Sun.COM 	int i;
24139353SSamuel.Tu@Sun.COM 	int secrxreg;
24149353SSamuel.Tu@Sun.COM 
241510998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_enable_rx_dma_82599");
241610998SChenlu.Chen@Sun.COM 
24179353SSamuel.Tu@Sun.COM 	/*
24189353SSamuel.Tu@Sun.COM 	 * Workaround for 82599 silicon errata when enabling the Rx datapath.
24199353SSamuel.Tu@Sun.COM 	 * If traffic is incoming before we enable the Rx unit, it could hang
24209353SSamuel.Tu@Sun.COM 	 * the Rx DMA unit.  Therefore, make sure the security engine is
24219353SSamuel.Tu@Sun.COM 	 * completely disabled prior to enabling the Rx unit.
24229353SSamuel.Tu@Sun.COM 	 */
24239353SSamuel.Tu@Sun.COM 	secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
24249353SSamuel.Tu@Sun.COM 	secrxreg |= IXGBE_SECRXCTRL_RX_DIS;
24259353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
24269353SSamuel.Tu@Sun.COM 	for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) {
24279353SSamuel.Tu@Sun.COM 		secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT);
24289353SSamuel.Tu@Sun.COM 		if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY)
24299353SSamuel.Tu@Sun.COM 			break;
24309353SSamuel.Tu@Sun.COM 		else
24319353SSamuel.Tu@Sun.COM 			/* Use interrupt-safe sleep just in case */
24329353SSamuel.Tu@Sun.COM 			usec_delay(10);
24339353SSamuel.Tu@Sun.COM 	}
24349353SSamuel.Tu@Sun.COM 
24359353SSamuel.Tu@Sun.COM 	/* For informational purposes only */
24369353SSamuel.Tu@Sun.COM 	if (i >= IXGBE_MAX_SECRX_POLL)
24379353SSamuel.Tu@Sun.COM 		DEBUGOUT("Rx unit being enabled before security "
24389353SSamuel.Tu@Sun.COM 		    "path fully disabled.	Continuing with init.\n");
24399353SSamuel.Tu@Sun.COM 
24409353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
24419353SSamuel.Tu@Sun.COM 	secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
24429353SSamuel.Tu@Sun.COM 	secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS;
24439353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
24449353SSamuel.Tu@Sun.COM 	IXGBE_WRITE_FLUSH(hw);
24459353SSamuel.Tu@Sun.COM 
24469353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
24479353SSamuel.Tu@Sun.COM }
24489353SSamuel.Tu@Sun.COM 
24499353SSamuel.Tu@Sun.COM /*
24509353SSamuel.Tu@Sun.COM  * ixgbe_get_device_caps_82599 - Get additional device capabilities
24519353SSamuel.Tu@Sun.COM  * @hw: pointer to hardware structure
24529353SSamuel.Tu@Sun.COM  * @device_caps: the EEPROM word with the extra device capabilities
24539353SSamuel.Tu@Sun.COM  *
24549353SSamuel.Tu@Sun.COM  * This function will read the EEPROM location for the device capabilities,
24559353SSamuel.Tu@Sun.COM  * and return the word through device_caps.
24569353SSamuel.Tu@Sun.COM  */
24579353SSamuel.Tu@Sun.COM s32
ixgbe_get_device_caps_82599(struct ixgbe_hw * hw,u16 * device_caps)24589353SSamuel.Tu@Sun.COM ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps)
24599353SSamuel.Tu@Sun.COM {
246010998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_get_device_caps_82599");
246110998SChenlu.Chen@Sun.COM 
24629353SSamuel.Tu@Sun.COM 	hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
24639353SSamuel.Tu@Sun.COM 
24649353SSamuel.Tu@Sun.COM 	return (IXGBE_SUCCESS);
24659353SSamuel.Tu@Sun.COM }
24669353SSamuel.Tu@Sun.COM 
24679353SSamuel.Tu@Sun.COM /*
246810305SPaul.Guo@Sun.COM  * ixgbe_verify_fw_version_82599 - verify fw version for 82599
246910305SPaul.Guo@Sun.COM  * @hw: pointer to hardware structure
247010305SPaul.Guo@Sun.COM  *
247110305SPaul.Guo@Sun.COM  * Verifies that installed the firmware version is 0.6 or higher
247210305SPaul.Guo@Sun.COM  * for SFI devices. All 82599 SFI devices should have version 0.6 or higher.
247310305SPaul.Guo@Sun.COM  *
247410305SPaul.Guo@Sun.COM  * Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or
247510305SPaul.Guo@Sun.COM  * if the FW version is not supported.
247610305SPaul.Guo@Sun.COM  */
247710305SPaul.Guo@Sun.COM static s32
ixgbe_verify_fw_version_82599(struct ixgbe_hw * hw)247810305SPaul.Guo@Sun.COM ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
247910305SPaul.Guo@Sun.COM {
248010305SPaul.Guo@Sun.COM 	s32 status = IXGBE_ERR_EEPROM_VERSION;
248110305SPaul.Guo@Sun.COM 	u16 fw_offset, fw_ptp_cfg_offset;
248210305SPaul.Guo@Sun.COM 	u16 fw_version = 0;
248310305SPaul.Guo@Sun.COM 
248410998SChenlu.Chen@Sun.COM 	DEBUGFUNC("ixgbe_verify_fw_version_82599");
248510998SChenlu.Chen@Sun.COM 
248610305SPaul.Guo@Sun.COM 	/* firmware check is only necessary for SFI devices */
248710305SPaul.Guo@Sun.COM 	if (hw->phy.media_type != ixgbe_media_type_fiber) {
248810305SPaul.Guo@Sun.COM 		status = IXGBE_SUCCESS;
248910305SPaul.Guo@Sun.COM 		goto fw_version_out;
249010305SPaul.Guo@Sun.COM 	}
249110305SPaul.Guo@Sun.COM 
249210305SPaul.Guo@Sun.COM 	/* get the offset to the Firmware Module block */
249310305SPaul.Guo@Sun.COM 	hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
249410305SPaul.Guo@Sun.COM 
249510305SPaul.Guo@Sun.COM 	if ((fw_offset == 0) || (fw_offset == 0xFFFF))
249610305SPaul.Guo@Sun.COM 		goto fw_version_out;
249710305SPaul.Guo@Sun.COM 
249810305SPaul.Guo@Sun.COM 	/* get the offset to the Pass Through Patch Configuration block */
249910305SPaul.Guo@Sun.COM 	hw->eeprom.ops.read(hw, (fw_offset +
250010305SPaul.Guo@Sun.COM 	    IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR), &fw_ptp_cfg_offset);
250110305SPaul.Guo@Sun.COM 
250210305SPaul.Guo@Sun.COM 	if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
250310305SPaul.Guo@Sun.COM 		goto fw_version_out;
250410305SPaul.Guo@Sun.COM 
250510305SPaul.Guo@Sun.COM 	/* get the firmware version */
250610305SPaul.Guo@Sun.COM 	hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4),
250710305SPaul.Guo@Sun.COM 	    &fw_version);
250810305SPaul.Guo@Sun.COM 
250910305SPaul.Guo@Sun.COM 	if (fw_version > 0x5)
251010305SPaul.Guo@Sun.COM 		status = IXGBE_SUCCESS;
251110305SPaul.Guo@Sun.COM 
251210305SPaul.Guo@Sun.COM fw_version_out:
251310305SPaul.Guo@Sun.COM 	return (status);
251410305SPaul.Guo@Sun.COM }
251512003SPaul.Guo@Sun.COM 
251612003SPaul.Guo@Sun.COM /*
251712003SPaul.Guo@Sun.COM  * ixgbe_enable_relaxed_ordering_82599 - Enable relaxed ordering
251812003SPaul.Guo@Sun.COM  * @hw: pointer to hardware structure
251912003SPaul.Guo@Sun.COM  */
252012003SPaul.Guo@Sun.COM void
ixgbe_enable_relaxed_ordering_82599(struct ixgbe_hw * hw)252112003SPaul.Guo@Sun.COM ixgbe_enable_relaxed_ordering_82599(struct ixgbe_hw *hw)
252212003SPaul.Guo@Sun.COM {
252312003SPaul.Guo@Sun.COM 	u32 regval;
252412003SPaul.Guo@Sun.COM 	u32 i;
252512003SPaul.Guo@Sun.COM 
252612003SPaul.Guo@Sun.COM 	DEBUGFUNC("ixgbe_enable_relaxed_ordering_82599");
252712003SPaul.Guo@Sun.COM 
252812003SPaul.Guo@Sun.COM 	/* Enable relaxed ordering */
252912003SPaul.Guo@Sun.COM 	for (i = 0; i < hw->mac.max_tx_queues; i++) {
253012003SPaul.Guo@Sun.COM 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
253112003SPaul.Guo@Sun.COM 		regval |= IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
253212003SPaul.Guo@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
253312003SPaul.Guo@Sun.COM 	}
253412003SPaul.Guo@Sun.COM 
253512003SPaul.Guo@Sun.COM 	for (i = 0; i < hw->mac.max_rx_queues; i++) {
253612003SPaul.Guo@Sun.COM 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
253712003SPaul.Guo@Sun.COM 		regval |= (IXGBE_DCA_RXCTRL_DESC_WRO_EN |
253812003SPaul.Guo@Sun.COM 		    IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
253912003SPaul.Guo@Sun.COM 		IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
254012003SPaul.Guo@Sun.COM 	}
254112003SPaul.Guo@Sun.COM }
2542