163b3bba8SJerry Jelinek /******************************************************************************
2*48ed61a7SRobert Mustacchi   SPDX-License-Identifier: BSD-3-Clause
363b3bba8SJerry Jelinek 
4*48ed61a7SRobert Mustacchi   Copyright (c) 2001-2017, Intel Corporation
563b3bba8SJerry Jelinek   All rights reserved.
6*48ed61a7SRobert Mustacchi 
7*48ed61a7SRobert Mustacchi   Redistribution and use in source and binary forms, with or without
863b3bba8SJerry Jelinek   modification, are permitted provided that the following conditions are met:
9*48ed61a7SRobert Mustacchi 
10*48ed61a7SRobert Mustacchi    1. Redistributions of source code must retain the above copyright notice,
1163b3bba8SJerry Jelinek       this list of conditions and the following disclaimer.
12*48ed61a7SRobert Mustacchi 
13*48ed61a7SRobert Mustacchi    2. Redistributions in binary form must reproduce the above copyright
14*48ed61a7SRobert Mustacchi       notice, this list of conditions and the following disclaimer in the
1563b3bba8SJerry Jelinek       documentation and/or other materials provided with the distribution.
16*48ed61a7SRobert Mustacchi 
17*48ed61a7SRobert Mustacchi    3. Neither the name of the Intel Corporation nor the names of its
18*48ed61a7SRobert Mustacchi       contributors may be used to endorse or promote products derived from
1963b3bba8SJerry Jelinek       this software without specific prior written permission.
20*48ed61a7SRobert Mustacchi 
2163b3bba8SJerry Jelinek   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22*48ed61a7SRobert Mustacchi   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*48ed61a7SRobert Mustacchi   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*48ed61a7SRobert Mustacchi   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25*48ed61a7SRobert Mustacchi   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26*48ed61a7SRobert Mustacchi   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27*48ed61a7SRobert Mustacchi   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*48ed61a7SRobert Mustacchi   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*48ed61a7SRobert Mustacchi   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3063b3bba8SJerry Jelinek   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3163b3bba8SJerry Jelinek   POSSIBILITY OF SUCH DAMAGE.
3263b3bba8SJerry Jelinek 
3363b3bba8SJerry Jelinek ******************************************************************************/
34dc0cb1cdSDale Ghent /*$FreeBSD$*/
359da57d7bSbt 
369da57d7bSbt #include "ixgbe_common.h"
375b6dd21fSchenlu chen - Sun Microsystems - Beijing China #include "ixgbe_phy.h"
38dc0cb1cdSDale Ghent #include "ixgbe_dcb.h"
39dc0cb1cdSDale Ghent #include "ixgbe_dcb_82599.h"
409da57d7bSbt #include "ixgbe_api.h"
419da57d7bSbt 
429da57d7bSbt static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
439da57d7bSbt static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
449da57d7bSbt static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
459da57d7bSbt static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw);
469da57d7bSbt static void ixgbe_standby_eeprom(struct ixgbe_hw *hw);
479da57d7bSbt static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
4869b5a878SDan McDonald 					u16 count);
499da57d7bSbt static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count);
509da57d7bSbt static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
519da57d7bSbt static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
529da57d7bSbt static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
539da57d7bSbt 
549da57d7bSbt static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
553cfa0eb9Schenlu chen - Sun Microsystems - Beijing China static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
5669b5a878SDan McDonald 					 u16 *san_mac_offset);
5769b5a878SDan McDonald static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
5869b5a878SDan McDonald 					     u16 words, u16 *data);
5969b5a878SDan McDonald static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
6069b5a878SDan McDonald 					      u16 words, u16 *data);
6169b5a878SDan McDonald static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
6269b5a878SDan McDonald 						 u16 offset);
639da57d7bSbt 
6463b3bba8SJerry Jelinek /**
6563b3bba8SJerry Jelinek  *  ixgbe_init_ops_generic - Inits function ptrs
6663b3bba8SJerry Jelinek  *  @hw: pointer to the hardware structure
679da57d7bSbt  *
6863b3bba8SJerry Jelinek  *  Initialize the function pointers.
6963b3bba8SJerry Jelinek  **/
ixgbe_init_ops_generic(struct ixgbe_hw * hw)7063b3bba8SJerry Jelinek s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
719da57d7bSbt {
729da57d7bSbt 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
739da57d7bSbt 	struct ixgbe_mac_info *mac = &hw->mac;
74dc0cb1cdSDale Ghent 	u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
759da57d7bSbt 
763cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_init_ops_generic");
773cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
789da57d7bSbt 	/* EEPROM */
79dc0cb1cdSDale Ghent 	eeprom->ops.init_params = ixgbe_init_eeprom_params_generic;
8013740cb2SPaul Guo 	/* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
8169b5a878SDan McDonald 	if (eec & IXGBE_EEC_PRES) {
82dc0cb1cdSDale Ghent 		eeprom->ops.read = ixgbe_read_eerd_generic;
83dc0cb1cdSDale Ghent 		eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic;
8469b5a878SDan McDonald 	} else {
85dc0cb1cdSDale Ghent 		eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic;
8669b5a878SDan McDonald 		eeprom->ops.read_buffer =
87dc0cb1cdSDale Ghent 				 ixgbe_read_eeprom_buffer_bit_bang_generic;
8869b5a878SDan McDonald 	}
89dc0cb1cdSDale Ghent 	eeprom->ops.write = ixgbe_write_eeprom_generic;
90dc0cb1cdSDale Ghent 	eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic;
919da57d7bSbt 	eeprom->ops.validate_checksum =
92dc0cb1cdSDale Ghent 				      ixgbe_validate_eeprom_checksum_generic;
93dc0cb1cdSDale Ghent 	eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic;
94dc0cb1cdSDale Ghent 	eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic;
959da57d7bSbt 
969da57d7bSbt 	/* MAC */
97dc0cb1cdSDale Ghent 	mac->ops.init_hw = ixgbe_init_hw_generic;
989da57d7bSbt 	mac->ops.reset_hw = NULL;
99dc0cb1cdSDale Ghent 	mac->ops.start_hw = ixgbe_start_hw_generic;
100dc0cb1cdSDale Ghent 	mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic;
1019da57d7bSbt 	mac->ops.get_media_type = NULL;
10213740cb2SPaul Guo 	mac->ops.get_supported_physical_layer = NULL;
103dc0cb1cdSDale Ghent 	mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic;
104dc0cb1cdSDale Ghent 	mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic;
105dc0cb1cdSDale Ghent 	mac->ops.stop_adapter = ixgbe_stop_adapter_generic;
106dc0cb1cdSDale Ghent 	mac->ops.get_bus_info = ixgbe_get_bus_info_generic;
107dc0cb1cdSDale Ghent 	mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie;
108dc0cb1cdSDale Ghent 	mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync;
109dc0cb1cdSDale Ghent 	mac->ops.release_swfw_sync = ixgbe_release_swfw_sync;
110dc0cb1cdSDale Ghent 	mac->ops.prot_autoc_read = prot_autoc_read_generic;
111dc0cb1cdSDale Ghent 	mac->ops.prot_autoc_write = prot_autoc_write_generic;
1129da57d7bSbt 
1139da57d7bSbt 	/* LEDs */
114dc0cb1cdSDale Ghent 	mac->ops.led_on = ixgbe_led_on_generic;
115dc0cb1cdSDale Ghent 	mac->ops.led_off = ixgbe_led_off_generic;
116dc0cb1cdSDale Ghent 	mac->ops.blink_led_start = ixgbe_blink_led_start_generic;
117dc0cb1cdSDale Ghent 	mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic;
118*48ed61a7SRobert Mustacchi 	mac->ops.init_led_link_act = ixgbe_init_led_link_act_generic;
1199da57d7bSbt 
1209da57d7bSbt 	/* RAR, Multicast, VLAN */
121dc0cb1cdSDale Ghent 	mac->ops.set_rar = ixgbe_set_rar_generic;
122dc0cb1cdSDale Ghent 	mac->ops.clear_rar = ixgbe_clear_rar_generic;
12373cd555cSBin Tu - Sun Microsystems - Beijing China 	mac->ops.insert_mac_addr = NULL;
1249da57d7bSbt 	mac->ops.set_vmdq = NULL;
12513740cb2SPaul Guo 	mac->ops.clear_vmdq = NULL;
126dc0cb1cdSDale Ghent 	mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic;
127dc0cb1cdSDale Ghent 	mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic;
128dc0cb1cdSDale Ghent 	mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic;
129dc0cb1cdSDale Ghent 	mac->ops.enable_mc = ixgbe_enable_mc_generic;
130dc0cb1cdSDale Ghent 	mac->ops.disable_mc = ixgbe_disable_mc_generic;
13113740cb2SPaul Guo 	mac->ops.clear_vfta = NULL;
13213740cb2SPaul Guo 	mac->ops.set_vfta = NULL;
13369b5a878SDan McDonald 	mac->ops.set_vlvf = NULL;
13413740cb2SPaul Guo 	mac->ops.init_uta_tables = NULL;
135dc0cb1cdSDale Ghent 	mac->ops.enable_rx = ixgbe_enable_rx_generic;
136dc0cb1cdSDale Ghent 	mac->ops.disable_rx = ixgbe_disable_rx_generic;
1379da57d7bSbt 
1389da57d7bSbt 	/* Flow Control */
139dc0cb1cdSDale Ghent 	mac->ops.fc_enable = ixgbe_fc_enable_generic;
140dc0cb1cdSDale Ghent 	mac->ops.setup_fc = ixgbe_setup_fc_generic;
141*48ed61a7SRobert Mustacchi 	mac->ops.fc_autoneg = ixgbe_fc_autoneg;
1429da57d7bSbt 
1439da57d7bSbt 	/* Link */
1449da57d7bSbt 	mac->ops.get_link_capabilities = NULL;
1459da57d7bSbt 	mac->ops.setup_link = NULL;
1469da57d7bSbt 	mac->ops.check_link = NULL;
147dc0cb1cdSDale Ghent 	mac->ops.dmac_config = NULL;
148dc0cb1cdSDale Ghent 	mac->ops.dmac_update_tcs = NULL;
149dc0cb1cdSDale Ghent 	mac->ops.dmac_config_tcs = NULL;
1509da57d7bSbt 
15163b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
1529da57d7bSbt }
1539da57d7bSbt 
15469b5a878SDan McDonald /**
155dc0cb1cdSDale Ghent  * ixgbe_device_supports_autoneg_fc - Check if device supports autonegotiation
156dc0cb1cdSDale Ghent  * of flow control
157dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
158dc0cb1cdSDale Ghent  *
159dc0cb1cdSDale Ghent  * This function returns TRUE if the device supports flow control
160dc0cb1cdSDale Ghent  * autonegotiation, and FALSE if it does not.
16169b5a878SDan McDonald  *
16269b5a878SDan McDonald  **/
ixgbe_device_supports_autoneg_fc(struct ixgbe_hw * hw)163dc0cb1cdSDale Ghent bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
16469b5a878SDan McDonald {
165dc0cb1cdSDale Ghent 	bool supported = FALSE;
166dc0cb1cdSDale Ghent 	ixgbe_link_speed speed;
167dc0cb1cdSDale Ghent 	bool link_up;
16869b5a878SDan McDonald 
16969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_device_supports_autoneg_fc");
17069b5a878SDan McDonald 
171dc0cb1cdSDale Ghent 	switch (hw->phy.media_type) {
172dc0cb1cdSDale Ghent 	case ixgbe_media_type_fiber_fixed:
173dc0cb1cdSDale Ghent 	case ixgbe_media_type_fiber_qsfp:
174dc0cb1cdSDale Ghent 	case ixgbe_media_type_fiber:
175*48ed61a7SRobert Mustacchi 		/* flow control autoneg black list */
176*48ed61a7SRobert Mustacchi 		switch (hw->device_id) {
177*48ed61a7SRobert Mustacchi 		case IXGBE_DEV_ID_X550EM_A_SFP:
178*48ed61a7SRobert Mustacchi 		case IXGBE_DEV_ID_X550EM_A_SFP_N:
179*48ed61a7SRobert Mustacchi 		case IXGBE_DEV_ID_X550EM_A_QSFP:
180*48ed61a7SRobert Mustacchi 		case IXGBE_DEV_ID_X550EM_A_QSFP_N:
181*48ed61a7SRobert Mustacchi 			supported = FALSE;
182*48ed61a7SRobert Mustacchi 			break;
183*48ed61a7SRobert Mustacchi 		default:
184*48ed61a7SRobert Mustacchi 			hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
185*48ed61a7SRobert Mustacchi 			/* if link is down, assume supported */
186*48ed61a7SRobert Mustacchi 			if (link_up)
187*48ed61a7SRobert Mustacchi 				supported = speed == IXGBE_LINK_SPEED_1GB_FULL ?
188dc0cb1cdSDale Ghent 				TRUE : FALSE;
189*48ed61a7SRobert Mustacchi 			else
190*48ed61a7SRobert Mustacchi 				supported = TRUE;
191*48ed61a7SRobert Mustacchi 		}
192*48ed61a7SRobert Mustacchi 
193dc0cb1cdSDale Ghent 		break;
194dc0cb1cdSDale Ghent 	case ixgbe_media_type_backplane:
195*48ed61a7SRobert Mustacchi 		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI)
196*48ed61a7SRobert Mustacchi 			supported = FALSE;
197*48ed61a7SRobert Mustacchi 		else
198*48ed61a7SRobert Mustacchi 			supported = TRUE;
199dc0cb1cdSDale Ghent 		break;
200dc0cb1cdSDale Ghent 	case ixgbe_media_type_copper:
201dc0cb1cdSDale Ghent 		/* only some copper devices support flow control autoneg */
202dc0cb1cdSDale Ghent 		switch (hw->device_id) {
203dc0cb1cdSDale Ghent 		case IXGBE_DEV_ID_82599_T3_LOM:
204dc0cb1cdSDale Ghent 		case IXGBE_DEV_ID_X540T:
205dc0cb1cdSDale Ghent 		case IXGBE_DEV_ID_X540T1:
206dc0cb1cdSDale Ghent 		case IXGBE_DEV_ID_X540_BYPASS:
207dc0cb1cdSDale Ghent 		case IXGBE_DEV_ID_X550T:
208dc0cb1cdSDale Ghent 		case IXGBE_DEV_ID_X550T1:
209dc0cb1cdSDale Ghent 		case IXGBE_DEV_ID_X550EM_X_10G_T:
210*48ed61a7SRobert Mustacchi 		case IXGBE_DEV_ID_X550EM_A_10G_T:
211*48ed61a7SRobert Mustacchi 		case IXGBE_DEV_ID_X550EM_A_1G_T:
212*48ed61a7SRobert Mustacchi 		case IXGBE_DEV_ID_X550EM_A_1G_T_L:
213dc0cb1cdSDale Ghent 			supported = TRUE;
214dc0cb1cdSDale Ghent 			break;
215dc0cb1cdSDale Ghent 		default:
216dc0cb1cdSDale Ghent 			supported = FALSE;
217dc0cb1cdSDale Ghent 		}
21869b5a878SDan McDonald 	default:
219dc0cb1cdSDale Ghent 		break;
220dc0cb1cdSDale Ghent 	}
221dc0cb1cdSDale Ghent 
222*48ed61a7SRobert Mustacchi 	if (!supported)
223dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
224*48ed61a7SRobert Mustacchi 			      "Device %x does not support flow control autoneg",
225*48ed61a7SRobert Mustacchi 			      hw->device_id);
226dc0cb1cdSDale Ghent 
227dc0cb1cdSDale Ghent 	return supported;
22869b5a878SDan McDonald }
22969b5a878SDan McDonald 
23069b5a878SDan McDonald /**
231dc0cb1cdSDale Ghent  *  ixgbe_setup_fc_generic - Set up flow control
23269b5a878SDan McDonald  *  @hw: pointer to hardware structure
23369b5a878SDan McDonald  *
23469b5a878SDan McDonald  *  Called at init time to set up flow control.
23569b5a878SDan McDonald  **/
ixgbe_setup_fc_generic(struct ixgbe_hw * hw)236dc0cb1cdSDale Ghent s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw)
23769b5a878SDan McDonald {
23869b5a878SDan McDonald 	s32 ret_val = IXGBE_SUCCESS;
23969b5a878SDan McDonald 	u32 reg = 0, reg_bp = 0;
24069b5a878SDan McDonald 	u16 reg_cu = 0;
241dc0cb1cdSDale Ghent 	bool locked = FALSE;
24269b5a878SDan McDonald 
243dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_setup_fc_generic");
24469b5a878SDan McDonald 
245dc0cb1cdSDale Ghent 	/* Validate the requested mode */
24669b5a878SDan McDonald 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
247dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
248dc0cb1cdSDale Ghent 			   "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
24969b5a878SDan McDonald 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
25069b5a878SDan McDonald 		goto out;
25169b5a878SDan McDonald 	}
25269b5a878SDan McDonald 
25369b5a878SDan McDonald 	/*
25469b5a878SDan McDonald 	 * 10gig parts do not have a word in the EEPROM to determine the
25569b5a878SDan McDonald 	 * default flow control setting, so we explicitly set it to full.
25669b5a878SDan McDonald 	 */
25769b5a878SDan McDonald 	if (hw->fc.requested_mode == ixgbe_fc_default)
25869b5a878SDan McDonald 		hw->fc.requested_mode = ixgbe_fc_full;
25969b5a878SDan McDonald 
26069b5a878SDan McDonald 	/*
26169b5a878SDan McDonald 	 * Set up the 1G and 10G flow control advertisement registers so the
26269b5a878SDan McDonald 	 * HW will be able to do fc autoneg once the cable is plugged in.  If
26369b5a878SDan McDonald 	 * we link at 10G, the 1G advertisement is harmless and vice versa.
26469b5a878SDan McDonald 	 */
26569b5a878SDan McDonald 	switch (hw->phy.media_type) {
26669b5a878SDan McDonald 	case ixgbe_media_type_backplane:
267dc0cb1cdSDale Ghent 		/* some MAC's need RMW protection on AUTOC */
268dc0cb1cdSDale Ghent 		ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &reg_bp);
269dc0cb1cdSDale Ghent 		if (ret_val != IXGBE_SUCCESS)
270dc0cb1cdSDale Ghent 			goto out;
271dc0cb1cdSDale Ghent 
272e5c421abSToomas Soome 		/* only backplane uses autoc */
273e5c421abSToomas Soome 		/* FALLTHROUGH */
274dc0cb1cdSDale Ghent 	case ixgbe_media_type_fiber_fixed:
275dc0cb1cdSDale Ghent 	case ixgbe_media_type_fiber_qsfp:
276dc0cb1cdSDale Ghent 	case ixgbe_media_type_fiber:
27769b5a878SDan McDonald 		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
278dc0cb1cdSDale Ghent 
27969b5a878SDan McDonald 		break;
28069b5a878SDan McDonald 	case ixgbe_media_type_copper:
28169b5a878SDan McDonald 		hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
28269b5a878SDan McDonald 				     IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg_cu);
28369b5a878SDan McDonald 		break;
28469b5a878SDan McDonald 	default:
28569b5a878SDan McDonald 		break;
28669b5a878SDan McDonald 	}
28769b5a878SDan McDonald 
28869b5a878SDan McDonald 	/*
28969b5a878SDan McDonald 	 * The possible values of fc.requested_mode are:
29069b5a878SDan McDonald 	 * 0: Flow control is completely disabled
29169b5a878SDan McDonald 	 * 1: Rx flow control is enabled (we can receive pause frames,
29269b5a878SDan McDonald 	 *    but not send pause frames).
29369b5a878SDan McDonald 	 * 2: Tx flow control is enabled (we can send pause frames but
29469b5a878SDan McDonald 	 *    we do not support receiving pause frames).
29569b5a878SDan McDonald 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
29669b5a878SDan McDonald 	 * other: Invalid.
29769b5a878SDan McDonald 	 */
29869b5a878SDan McDonald 	switch (hw->fc.requested_mode) {
29969b5a878SDan McDonald 	case ixgbe_fc_none:
30069b5a878SDan McDonald 		/* Flow control completely disabled by software override. */
30169b5a878SDan McDonald 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
30269b5a878SDan McDonald 		if (hw->phy.media_type == ixgbe_media_type_backplane)
30369b5a878SDan McDonald 			reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
30469b5a878SDan McDonald 				    IXGBE_AUTOC_ASM_PAUSE);
30569b5a878SDan McDonald 		else if (hw->phy.media_type == ixgbe_media_type_copper)
30669b5a878SDan McDonald 			reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
30769b5a878SDan McDonald 		break;
30869b5a878SDan McDonald 	case ixgbe_fc_tx_pause:
30969b5a878SDan McDonald 		/*
31069b5a878SDan McDonald 		 * Tx Flow control is enabled, and Rx Flow control is
31169b5a878SDan McDonald 		 * disabled by software override.
31269b5a878SDan McDonald 		 */
31369b5a878SDan McDonald 		reg |= IXGBE_PCS1GANA_ASM_PAUSE;
31469b5a878SDan McDonald 		reg &= ~IXGBE_PCS1GANA_SYM_PAUSE;
31569b5a878SDan McDonald 		if (hw->phy.media_type == ixgbe_media_type_backplane) {
31669b5a878SDan McDonald 			reg_bp |= IXGBE_AUTOC_ASM_PAUSE;
31769b5a878SDan McDonald 			reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE;
31869b5a878SDan McDonald 		} else if (hw->phy.media_type == ixgbe_media_type_copper) {
31969b5a878SDan McDonald 			reg_cu |= IXGBE_TAF_ASM_PAUSE;
32069b5a878SDan McDonald 			reg_cu &= ~IXGBE_TAF_SYM_PAUSE;
32169b5a878SDan McDonald 		}
32269b5a878SDan McDonald 		break;
32369b5a878SDan McDonald 	case ixgbe_fc_rx_pause:
32469b5a878SDan McDonald 		/*
32569b5a878SDan McDonald 		 * Rx Flow control is enabled and Tx Flow control is
32669b5a878SDan McDonald 		 * disabled by software override. Since there really
32769b5a878SDan McDonald 		 * isn't a way to advertise that we are capable of RX
32869b5a878SDan McDonald 		 * Pause ONLY, we will advertise that we support both
32969b5a878SDan McDonald 		 * symmetric and asymmetric Rx PAUSE, as such we fall
33069b5a878SDan McDonald 		 * through to the fc_full statement.  Later, we will
33169b5a878SDan McDonald 		 * disable the adapter's ability to send PAUSE frames.
33269b5a878SDan McDonald 		 */
33369b5a878SDan McDonald 	case ixgbe_fc_full:
33469b5a878SDan McDonald 		/* Flow control (both Rx and Tx) is enabled by SW override. */
33569b5a878SDan McDonald 		reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE;
33669b5a878SDan McDonald 		if (hw->phy.media_type == ixgbe_media_type_backplane)
33769b5a878SDan McDonald 			reg_bp |= IXGBE_AUTOC_SYM_PAUSE |
33869b5a878SDan McDonald 				  IXGBE_AUTOC_ASM_PAUSE;
33969b5a878SDan McDonald 		else if (hw->phy.media_type == ixgbe_media_type_copper)
34069b5a878SDan McDonald 			reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE;
34169b5a878SDan McDonald 		break;
34269b5a878SDan McDonald 	default:
343dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
344dc0cb1cdSDale Ghent 			     "Flow control param set incorrectly\n");
34569b5a878SDan McDonald 		ret_val = IXGBE_ERR_CONFIG;
34669b5a878SDan McDonald 		goto out;
347dc0cb1cdSDale Ghent 		break;
34869b5a878SDan McDonald 	}
34969b5a878SDan McDonald 
350dc0cb1cdSDale Ghent 	if (hw->mac.type < ixgbe_mac_X540) {
35169b5a878SDan McDonald 		/*
35269b5a878SDan McDonald 		 * Enable auto-negotiation between the MAC & PHY;
35369b5a878SDan McDonald 		 * the MAC will advertise clause 37 flow control.
35469b5a878SDan McDonald 		 */
35569b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
35669b5a878SDan McDonald 		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
35769b5a878SDan McDonald 
35869b5a878SDan McDonald 		/* Disable AN timeout */
35969b5a878SDan McDonald 		if (hw->fc.strict_ieee)
36069b5a878SDan McDonald 			reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
36169b5a878SDan McDonald 
36269b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
36369b5a878SDan McDonald 		DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
36469b5a878SDan McDonald 	}
36569b5a878SDan McDonald 
36669b5a878SDan McDonald 	/*
36769b5a878SDan McDonald 	 * AUTOC restart handles negotiation of 1G and 10G on backplane
36869b5a878SDan McDonald 	 * and copper. There is no need to set the PCS1GCTL register.
36969b5a878SDan McDonald 	 *
37069b5a878SDan McDonald 	 */
37169b5a878SDan McDonald 	if (hw->phy.media_type == ixgbe_media_type_backplane) {
37269b5a878SDan McDonald 		reg_bp |= IXGBE_AUTOC_AN_RESTART;
373dc0cb1cdSDale Ghent 		ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked);
374dc0cb1cdSDale Ghent 		if (ret_val)
375dc0cb1cdSDale Ghent 			goto out;
37669b5a878SDan McDonald 	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
377dc0cb1cdSDale Ghent 		    (ixgbe_device_supports_autoneg_fc(hw))) {
37869b5a878SDan McDonald 		hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
37969b5a878SDan McDonald 				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu);
38069b5a878SDan McDonald 	}
38169b5a878SDan McDonald 
382dc0cb1cdSDale Ghent 	DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
38369b5a878SDan McDonald out:
38469b5a878SDan McDonald 	return ret_val;
38569b5a878SDan McDonald }
38669b5a878SDan McDonald 
38763b3bba8SJerry Jelinek /**
38863b3bba8SJerry Jelinek  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
38963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
3909da57d7bSbt  *
39163b3bba8SJerry Jelinek  *  Starts the hardware by filling the bus info structure and media type, clears
39263b3bba8SJerry Jelinek  *  all on chip counters, initializes receive address registers, multicast
39363b3bba8SJerry Jelinek  *  table, VLAN filter table, calls routine to set up link and flow control
39463b3bba8SJerry Jelinek  *  settings, and leaves transmit and receive units disabled and uninitialized
39563b3bba8SJerry Jelinek  **/
ixgbe_start_hw_generic(struct ixgbe_hw * hw)39663b3bba8SJerry Jelinek s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
3979da57d7bSbt {
39869b5a878SDan McDonald 	s32 ret_val;
3999da57d7bSbt 	u32 ctrl_ext;
400*48ed61a7SRobert Mustacchi 	u16 device_caps;
4019da57d7bSbt 
4023cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_start_hw_generic");
4033cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
4049da57d7bSbt 	/* Set the media type */
4059da57d7bSbt 	hw->phy.media_type = hw->mac.ops.get_media_type(hw);
4069da57d7bSbt 
40773cd555cSBin Tu - Sun Microsystems - Beijing China 	/* PHY ops initialization must be done in reset_hw() */
4089da57d7bSbt 
4099da57d7bSbt 	/* Clear the VLAN filter table */
4109da57d7bSbt 	hw->mac.ops.clear_vfta(hw);
4119da57d7bSbt 
4129da57d7bSbt 	/* Clear statistics registers */
4139da57d7bSbt 	hw->mac.ops.clear_hw_cntrs(hw);
4149da57d7bSbt 
4159da57d7bSbt 	/* Set No Snoop Disable */
4169da57d7bSbt 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
4179da57d7bSbt 	ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
4189da57d7bSbt 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
4199da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
4209da57d7bSbt 
42173cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Setup flow control */
42269b5a878SDan McDonald 	ret_val = ixgbe_setup_fc(hw);
423*48ed61a7SRobert Mustacchi 	if (ret_val != IXGBE_SUCCESS && ret_val != IXGBE_NOT_IMPLEMENTED) {
424*48ed61a7SRobert Mustacchi 		DEBUGOUT1("Flow control setup failed, returning %d\n", ret_val);
425*48ed61a7SRobert Mustacchi 		return ret_val;
426*48ed61a7SRobert Mustacchi 	}
427*48ed61a7SRobert Mustacchi 
428*48ed61a7SRobert Mustacchi 	/* Cache bit indicating need for crosstalk fix */
429*48ed61a7SRobert Mustacchi 	switch (hw->mac.type) {
430*48ed61a7SRobert Mustacchi 	case ixgbe_mac_82599EB:
431*48ed61a7SRobert Mustacchi 	case ixgbe_mac_X550EM_x:
432*48ed61a7SRobert Mustacchi 	case ixgbe_mac_X550EM_a:
433*48ed61a7SRobert Mustacchi 		hw->mac.ops.get_device_caps(hw, &device_caps);
434*48ed61a7SRobert Mustacchi 		if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR)
435*48ed61a7SRobert Mustacchi 			hw->need_crosstalk_fix = FALSE;
436*48ed61a7SRobert Mustacchi 		else
437*48ed61a7SRobert Mustacchi 			hw->need_crosstalk_fix = TRUE;
438*48ed61a7SRobert Mustacchi 		break;
439*48ed61a7SRobert Mustacchi 	default:
440*48ed61a7SRobert Mustacchi 		hw->need_crosstalk_fix = FALSE;
441*48ed61a7SRobert Mustacchi 		break;
442*48ed61a7SRobert Mustacchi 	}
44373cd555cSBin Tu - Sun Microsystems - Beijing China 
4449da57d7bSbt 	/* Clear adapter stopped flag */
44563b3bba8SJerry Jelinek 	hw->adapter_stopped = FALSE;
4469da57d7bSbt 
447*48ed61a7SRobert Mustacchi 	return IXGBE_SUCCESS;
4489da57d7bSbt }
4499da57d7bSbt 
45063b3bba8SJerry Jelinek /**
45163b3bba8SJerry Jelinek  *  ixgbe_start_hw_gen2 - Init sequence for common device family
45263b3bba8SJerry Jelinek  *  @hw: pointer to hw structure
4539da57d7bSbt  *
45463b3bba8SJerry Jelinek  * Performs the init sequence common to the second generation
45563b3bba8SJerry Jelinek  * of 10 GbE devices.
45663b3bba8SJerry Jelinek  * Devices in the second generation:
45763b3bba8SJerry Jelinek  *     82599
45863b3bba8SJerry Jelinek  *     X540
45963b3bba8SJerry Jelinek  **/
ixgbe_start_hw_gen2(struct ixgbe_hw * hw)46063b3bba8SJerry Jelinek s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw)
4619da57d7bSbt {
46263b3bba8SJerry Jelinek 	u32 i;
46363b3bba8SJerry Jelinek 	u32 regval;
46463b3bba8SJerry Jelinek 
46563b3bba8SJerry Jelinek 	/* Clear the rate limiters */
46663b3bba8SJerry Jelinek 	for (i = 0; i < hw->mac.max_tx_queues; i++) {
46763b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i);
46863b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0);
46963b3bba8SJerry Jelinek 	}
47063b3bba8SJerry Jelinek 	IXGBE_WRITE_FLUSH(hw);
47163b3bba8SJerry Jelinek 
47263b3bba8SJerry Jelinek 	/* Disable relaxed ordering */
47363b3bba8SJerry Jelinek 	for (i = 0; i < hw->mac.max_tx_queues; i++) {
47463b3bba8SJerry Jelinek 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
47569b5a878SDan McDonald 		regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
47663b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
47763b3bba8SJerry Jelinek 	}
47863b3bba8SJerry Jelinek 
47963b3bba8SJerry Jelinek 	for (i = 0; i < hw->mac.max_rx_queues; i++) {
48063b3bba8SJerry Jelinek 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
48169b5a878SDan McDonald 		regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN |
48269b5a878SDan McDonald 			    IXGBE_DCA_RXCTRL_HEAD_WRO_EN);
48363b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
48463b3bba8SJerry Jelinek 	}
48563b3bba8SJerry Jelinek 
48663b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
48763b3bba8SJerry Jelinek }
48863b3bba8SJerry Jelinek 
48963b3bba8SJerry Jelinek /**
49063b3bba8SJerry Jelinek  *  ixgbe_init_hw_generic - Generic hardware initialization
49163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
49263b3bba8SJerry Jelinek  *
49363b3bba8SJerry Jelinek  *  Initialize the hardware by resetting the hardware, filling the bus info
49463b3bba8SJerry Jelinek  *  structure and media type, clears all on chip counters, initializes receive
49563b3bba8SJerry Jelinek  *  address registers, multicast table, VLAN filter table, calls routine to set
49663b3bba8SJerry Jelinek  *  up link and flow control settings, and leaves transmit and receive units
49763b3bba8SJerry Jelinek  *  disabled and uninitialized
49863b3bba8SJerry Jelinek  **/
ixgbe_init_hw_generic(struct ixgbe_hw * hw)49963b3bba8SJerry Jelinek s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
50063b3bba8SJerry Jelinek {
50163b3bba8SJerry Jelinek 	s32 status;
50273cd555cSBin Tu - Sun Microsystems - Beijing China 
5033cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_init_hw_generic");
5043cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
5059da57d7bSbt 	/* Reset the hardware */
50673cd555cSBin Tu - Sun Microsystems - Beijing China 	status = hw->mac.ops.reset_hw(hw);
5079da57d7bSbt 
508*48ed61a7SRobert Mustacchi 	if (status == IXGBE_SUCCESS || status == IXGBE_ERR_SFP_NOT_PRESENT) {
50973cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Start the HW */
51073cd555cSBin Tu - Sun Microsystems - Beijing China 		status = hw->mac.ops.start_hw(hw);
51173cd555cSBin Tu - Sun Microsystems - Beijing China 	}
5129da57d7bSbt 
513*48ed61a7SRobert Mustacchi 	/* Initialize the LED link active for LED blink support */
514*48ed61a7SRobert Mustacchi 	if (hw->mac.ops.init_led_link_act)
515*48ed61a7SRobert Mustacchi 		hw->mac.ops.init_led_link_act(hw);
516*48ed61a7SRobert Mustacchi 
517*48ed61a7SRobert Mustacchi 	if (status != IXGBE_SUCCESS)
518*48ed61a7SRobert Mustacchi 		DEBUGOUT1("Failed to initialize HW, STATUS = %d\n", status);
519*48ed61a7SRobert Mustacchi 
52063b3bba8SJerry Jelinek 	return status;
5219da57d7bSbt }
5229da57d7bSbt 
52363b3bba8SJerry Jelinek /**
52463b3bba8SJerry Jelinek  *  ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
52563b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
5269da57d7bSbt  *
52763b3bba8SJerry Jelinek  *  Clears all hardware statistics counters by reading them from the hardware
52863b3bba8SJerry Jelinek  *  Statistics counters are clear on read.
52963b3bba8SJerry Jelinek  **/
ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw * hw)53063b3bba8SJerry Jelinek s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
5319da57d7bSbt {
5329da57d7bSbt 	u16 i = 0;
5339da57d7bSbt 
5343cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_clear_hw_cntrs_generic");
5353cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
536dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_CRCERRS);
537dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_ILLERRC);
538dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_ERRBC);
539dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_MSPDC);
5409da57d7bSbt 	for (i = 0; i < 8; i++)
541dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_MPC(i));
5429da57d7bSbt 
543dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_MLFC);
544dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_MRFC);
545dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_RLEC);
546dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_LXONTXC);
547dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
54873cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->mac.type >= ixgbe_mac_82599EB) {
549dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
550dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
55173cd555cSBin Tu - Sun Microsystems - Beijing China 	} else {
552dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_LXONRXC);
553dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
55473cd555cSBin Tu - Sun Microsystems - Beijing China 	}
5559da57d7bSbt 
5569da57d7bSbt 	for (i = 0; i < 8; i++) {
557dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
558dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
55973cd555cSBin Tu - Sun Microsystems - Beijing China 		if (hw->mac.type >= ixgbe_mac_82599EB) {
560dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
561dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
56273cd555cSBin Tu - Sun Microsystems - Beijing China 		} else {
563dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
564dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
56573cd555cSBin Tu - Sun Microsystems - Beijing China 		}
5669da57d7bSbt 	}
56773cd555cSBin Tu - Sun Microsystems - Beijing China 	if (hw->mac.type >= ixgbe_mac_82599EB)
56873cd555cSBin Tu - Sun Microsystems - Beijing China 		for (i = 0; i < 8; i++)
569dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
570dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PRC64);
571dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PRC127);
572dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PRC255);
573dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PRC511);
574dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PRC1023);
575dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PRC1522);
576dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_GPRC);
577dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_BPRC);
578dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_MPRC);
579dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_GPTC);
580dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_GORCL);
581dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_GORCH);
582dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_GOTCL);
583dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_GOTCH);
58469b5a878SDan McDonald 	if (hw->mac.type == ixgbe_mac_82598EB)
58569b5a878SDan McDonald 		for (i = 0; i < 8; i++)
586dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_RNBC(i));
587dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_RUC);
588dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_RFC);
589dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_ROC);
590dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_RJC);
591dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_MNGPRC);
592dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_MNGPDC);
593dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_MNGPTC);
594dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_TORL);
595dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_TORH);
596dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_TPR);
597dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_TPT);
598dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PTC64);
599dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PTC127);
600dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PTC255);
601dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PTC511);
602dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PTC1023);
603dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_PTC1522);
604dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_MPTC);
605dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_BPTC);
6069da57d7bSbt 	for (i = 0; i < 16; i++) {
607dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_QPRC(i));
608dc0cb1cdSDale Ghent 		IXGBE_READ_REG(hw, IXGBE_QPTC(i));
60973cd555cSBin Tu - Sun Microsystems - Beijing China 		if (hw->mac.type >= ixgbe_mac_82599EB) {
610dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
611dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_QBRC_H(i));
612dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
613dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_QBTC_H(i));
614dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
61573cd555cSBin Tu - Sun Microsystems - Beijing China 		} else {
616dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_QBRC(i));
617dc0cb1cdSDale Ghent 			IXGBE_READ_REG(hw, IXGBE_QBTC(i));
61873cd555cSBin Tu - Sun Microsystems - Beijing China 		}
6199da57d7bSbt 	}
6209da57d7bSbt 
621dc0cb1cdSDale Ghent 	if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
62269b5a878SDan McDonald 		if (hw->phy.id == 0)
623dc0cb1cdSDale Ghent 			ixgbe_identify_phy(hw);
62469b5a878SDan McDonald 		hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL,
62569b5a878SDan McDonald 				     IXGBE_MDIO_PCS_DEV_TYPE, &i);
62669b5a878SDan McDonald 		hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH,
62769b5a878SDan McDonald 				     IXGBE_MDIO_PCS_DEV_TYPE, &i);
62869b5a878SDan McDonald 		hw->phy.ops.read_reg(hw, IXGBE_LDPCECL,
62969b5a878SDan McDonald 				     IXGBE_MDIO_PCS_DEV_TYPE, &i);
63069b5a878SDan McDonald 		hw->phy.ops.read_reg(hw, IXGBE_LDPCECH,
63169b5a878SDan McDonald 				     IXGBE_MDIO_PCS_DEV_TYPE, &i);
63269b5a878SDan McDonald 	}
63369b5a878SDan McDonald 
63463b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
6359da57d7bSbt }
6369da57d7bSbt 
63763b3bba8SJerry Jelinek /**
63863b3bba8SJerry Jelinek  *  ixgbe_read_pba_string_generic - Reads part number string from EEPROM
63963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
64063b3bba8SJerry Jelinek  *  @pba_num: stores the part number string from the EEPROM
64163b3bba8SJerry Jelinek  *  @pba_num_size: part number string buffer length
6429da57d7bSbt  *
64363b3bba8SJerry Jelinek  *  Reads the part number string from the EEPROM.
64463b3bba8SJerry Jelinek  **/
ixgbe_read_pba_string_generic(struct ixgbe_hw * hw,u8 * pba_num,u32 pba_num_size)64563b3bba8SJerry Jelinek s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num,
64669b5a878SDan McDonald 				  u32 pba_num_size)
64763b3bba8SJerry Jelinek {
64863b3bba8SJerry Jelinek 	s32 ret_val;
64963b3bba8SJerry Jelinek 	u16 data;
65063b3bba8SJerry Jelinek 	u16 pba_ptr;
65163b3bba8SJerry Jelinek 	u16 offset;
65263b3bba8SJerry Jelinek 	u16 length;
65363b3bba8SJerry Jelinek 
65463b3bba8SJerry Jelinek 	DEBUGFUNC("ixgbe_read_pba_string_generic");
65563b3bba8SJerry Jelinek 
65663b3bba8SJerry Jelinek 	if (pba_num == NULL) {
65763b3bba8SJerry Jelinek 		DEBUGOUT("PBA string buffer was null\n");
65863b3bba8SJerry Jelinek 		return IXGBE_ERR_INVALID_ARGUMENT;
65963b3bba8SJerry Jelinek 	}
66063b3bba8SJerry Jelinek 
66163b3bba8SJerry Jelinek 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
66263b3bba8SJerry Jelinek 	if (ret_val) {
66363b3bba8SJerry Jelinek 		DEBUGOUT("NVM Read Error\n");
66463b3bba8SJerry Jelinek 		return ret_val;
66563b3bba8SJerry Jelinek 	}
66663b3bba8SJerry Jelinek 
66763b3bba8SJerry Jelinek 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr);
66863b3bba8SJerry Jelinek 	if (ret_val) {
66963b3bba8SJerry Jelinek 		DEBUGOUT("NVM Read Error\n");
67063b3bba8SJerry Jelinek 		return ret_val;
67163b3bba8SJerry Jelinek 	}
67263b3bba8SJerry Jelinek 
67363b3bba8SJerry Jelinek 	/*
67463b3bba8SJerry Jelinek 	 * if data is not ptr guard the PBA must be in legacy format which
67563b3bba8SJerry Jelinek 	 * means pba_ptr is actually our second data word for the PBA number
67663b3bba8SJerry Jelinek 	 * and we can decode it into an ascii string
67763b3bba8SJerry Jelinek 	 */
67863b3bba8SJerry Jelinek 	if (data != IXGBE_PBANUM_PTR_GUARD) {
67963b3bba8SJerry Jelinek 		DEBUGOUT("NVM PBA number is not stored as string\n");
68063b3bba8SJerry Jelinek 
68163b3bba8SJerry Jelinek 		/* we will need 11 characters to store the PBA */
68263b3bba8SJerry Jelinek 		if (pba_num_size < 11) {
68363b3bba8SJerry Jelinek 			DEBUGOUT("PBA string buffer too small\n");
68463b3bba8SJerry Jelinek 			return IXGBE_ERR_NO_SPACE;
68563b3bba8SJerry Jelinek 		}
68663b3bba8SJerry Jelinek 
68763b3bba8SJerry Jelinek 		/* extract hex string from data and pba_ptr */
68863b3bba8SJerry Jelinek 		pba_num[0] = (data >> 12) & 0xF;
68963b3bba8SJerry Jelinek 		pba_num[1] = (data >> 8) & 0xF;
69063b3bba8SJerry Jelinek 		pba_num[2] = (data >> 4) & 0xF;
69163b3bba8SJerry Jelinek 		pba_num[3] = data & 0xF;
69263b3bba8SJerry Jelinek 		pba_num[4] = (pba_ptr >> 12) & 0xF;
69363b3bba8SJerry Jelinek 		pba_num[5] = (pba_ptr >> 8) & 0xF;
69463b3bba8SJerry Jelinek 		pba_num[6] = '-';
69563b3bba8SJerry Jelinek 		pba_num[7] = 0;
69663b3bba8SJerry Jelinek 		pba_num[8] = (pba_ptr >> 4) & 0xF;
69763b3bba8SJerry Jelinek 		pba_num[9] = pba_ptr & 0xF;
69863b3bba8SJerry Jelinek 
69963b3bba8SJerry Jelinek 		/* put a null character on the end of our string */
70063b3bba8SJerry Jelinek 		pba_num[10] = '\0';
70163b3bba8SJerry Jelinek 
70263b3bba8SJerry Jelinek 		/* switch all the data but the '-' to hex char */
70363b3bba8SJerry Jelinek 		for (offset = 0; offset < 10; offset++) {
70463b3bba8SJerry Jelinek 			if (pba_num[offset] < 0xA)
70563b3bba8SJerry Jelinek 				pba_num[offset] += '0';
70663b3bba8SJerry Jelinek 			else if (pba_num[offset] < 0x10)
70763b3bba8SJerry Jelinek 				pba_num[offset] += 'A' - 0xA;
70863b3bba8SJerry Jelinek 		}
70963b3bba8SJerry Jelinek 
71063b3bba8SJerry Jelinek 		return IXGBE_SUCCESS;
71163b3bba8SJerry Jelinek 	}
71263b3bba8SJerry Jelinek 
71363b3bba8SJerry Jelinek 	ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length);
71463b3bba8SJerry Jelinek 	if (ret_val) {
71563b3bba8SJerry Jelinek 		DEBUGOUT("NVM Read Error\n");
71663b3bba8SJerry Jelinek 		return ret_val;
71763b3bba8SJerry Jelinek 	}
71863b3bba8SJerry Jelinek 
71963b3bba8SJerry Jelinek 	if (length == 0xFFFF || length == 0) {
72063b3bba8SJerry Jelinek 		DEBUGOUT("NVM PBA number section invalid length\n");
72163b3bba8SJerry Jelinek 		return IXGBE_ERR_PBA_SECTION;
72263b3bba8SJerry Jelinek 	}
72363b3bba8SJerry Jelinek 
72463b3bba8SJerry Jelinek 	/* check if pba_num buffer is big enough */
72563b3bba8SJerry Jelinek 	if (pba_num_size  < (((u32)length * 2) - 1)) {
72663b3bba8SJerry Jelinek 		DEBUGOUT("PBA string buffer too small\n");
72763b3bba8SJerry Jelinek 		return IXGBE_ERR_NO_SPACE;
72863b3bba8SJerry Jelinek 	}
72963b3bba8SJerry Jelinek 
73063b3bba8SJerry Jelinek 	/* trim pba length from start of string */
73163b3bba8SJerry Jelinek 	pba_ptr++;
73263b3bba8SJerry Jelinek 	length--;
73363b3bba8SJerry Jelinek 
73463b3bba8SJerry Jelinek 	for (offset = 0; offset < length; offset++) {
73563b3bba8SJerry Jelinek 		ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data);
73663b3bba8SJerry Jelinek 		if (ret_val) {
73763b3bba8SJerry Jelinek 			DEBUGOUT("NVM Read Error\n");
73863b3bba8SJerry Jelinek 			return ret_val;
73963b3bba8SJerry Jelinek 		}
74063b3bba8SJerry Jelinek 		pba_num[offset * 2] = (u8)(data >> 8);
74163b3bba8SJerry Jelinek 		pba_num[(offset * 2) + 1] = (u8)(data & 0xFF);
74263b3bba8SJerry Jelinek 	}
74363b3bba8SJerry Jelinek 	pba_num[offset * 2] = '\0';
74463b3bba8SJerry Jelinek 
74563b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
74663b3bba8SJerry Jelinek }
74763b3bba8SJerry Jelinek 
74863b3bba8SJerry Jelinek /**
74963b3bba8SJerry Jelinek  *  ixgbe_read_pba_num_generic - Reads part number from EEPROM
75063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
75163b3bba8SJerry Jelinek  *  @pba_num: stores the part number from the EEPROM
75263b3bba8SJerry Jelinek  *
75363b3bba8SJerry Jelinek  *  Reads the part number from the EEPROM.
75463b3bba8SJerry Jelinek  **/
ixgbe_read_pba_num_generic(struct ixgbe_hw * hw,u32 * pba_num)75563b3bba8SJerry Jelinek s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num)
7569da57d7bSbt {
7579da57d7bSbt 	s32 ret_val;
7589da57d7bSbt 	u16 data;
7599da57d7bSbt 
7609da57d7bSbt 	DEBUGFUNC("ixgbe_read_pba_num_generic");
7619da57d7bSbt 
7629da57d7bSbt 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
7639da57d7bSbt 	if (ret_val) {
7649da57d7bSbt 		DEBUGOUT("NVM Read Error\n");
76563b3bba8SJerry Jelinek 		return ret_val;
76663b3bba8SJerry Jelinek 	} else if (data == IXGBE_PBANUM_PTR_GUARD) {
76763b3bba8SJerry Jelinek 		DEBUGOUT("NVM Not supported\n");
76863b3bba8SJerry Jelinek 		return IXGBE_NOT_IMPLEMENTED;
7699da57d7bSbt 	}
7709da57d7bSbt 	*pba_num = (u32)(data << 16);
7719da57d7bSbt 
7729da57d7bSbt 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data);
7739da57d7bSbt 	if (ret_val) {
7749da57d7bSbt 		DEBUGOUT("NVM Read Error\n");
77563b3bba8SJerry Jelinek 		return ret_val;
7769da57d7bSbt 	}
7779da57d7bSbt 	*pba_num |= data;
7789da57d7bSbt 
77963b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
7809da57d7bSbt }
7819da57d7bSbt 
782dc0cb1cdSDale Ghent /**
783dc0cb1cdSDale Ghent  *  ixgbe_read_pba_raw
784dc0cb1cdSDale Ghent  *  @hw: pointer to the HW structure
785dc0cb1cdSDale Ghent  *  @eeprom_buf: optional pointer to EEPROM image
786dc0cb1cdSDale Ghent  *  @eeprom_buf_size: size of EEPROM image in words
787dc0cb1cdSDale Ghent  *  @max_pba_block_size: PBA block size limit
788dc0cb1cdSDale Ghent  *  @pba: pointer to output PBA structure
789dc0cb1cdSDale Ghent  *
790dc0cb1cdSDale Ghent  *  Reads PBA from EEPROM image when eeprom_buf is not NULL.
791dc0cb1cdSDale Ghent  *  Reads PBA from physical EEPROM device when eeprom_buf is NULL.
792dc0cb1cdSDale Ghent  *
793dc0cb1cdSDale Ghent  **/
ixgbe_read_pba_raw(struct ixgbe_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,u16 max_pba_block_size,struct ixgbe_pba * pba)794dc0cb1cdSDale Ghent s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf,
795dc0cb1cdSDale Ghent 		       u32 eeprom_buf_size, u16 max_pba_block_size,
796dc0cb1cdSDale Ghent 		       struct ixgbe_pba *pba)
797dc0cb1cdSDale Ghent {
798dc0cb1cdSDale Ghent 	s32 ret_val;
799dc0cb1cdSDale Ghent 	u16 pba_block_size;
800dc0cb1cdSDale Ghent 
801dc0cb1cdSDale Ghent 	if (pba == NULL)
802dc0cb1cdSDale Ghent 		return IXGBE_ERR_PARAM;
803dc0cb1cdSDale Ghent 
804dc0cb1cdSDale Ghent 	if (eeprom_buf == NULL) {
805dc0cb1cdSDale Ghent 		ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2,
806dc0cb1cdSDale Ghent 						     &pba->word[0]);
807dc0cb1cdSDale Ghent 		if (ret_val)
808dc0cb1cdSDale Ghent 			return ret_val;
809dc0cb1cdSDale Ghent 	} else {
810dc0cb1cdSDale Ghent 		if (eeprom_buf_size > IXGBE_PBANUM1_PTR) {
811dc0cb1cdSDale Ghent 			pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR];
812dc0cb1cdSDale Ghent 			pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR];
813dc0cb1cdSDale Ghent 		} else {
814dc0cb1cdSDale Ghent 			return IXGBE_ERR_PARAM;
815dc0cb1cdSDale Ghent 		}
816dc0cb1cdSDale Ghent 	}
817dc0cb1cdSDale Ghent 
818dc0cb1cdSDale Ghent 	if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) {
819dc0cb1cdSDale Ghent 		if (pba->pba_block == NULL)
820dc0cb1cdSDale Ghent 			return IXGBE_ERR_PARAM;
821dc0cb1cdSDale Ghent 
822dc0cb1cdSDale Ghent 		ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf,
823dc0cb1cdSDale Ghent 						   eeprom_buf_size,
824dc0cb1cdSDale Ghent 						   &pba_block_size);
825dc0cb1cdSDale Ghent 		if (ret_val)
826dc0cb1cdSDale Ghent 			return ret_val;
827dc0cb1cdSDale Ghent 
828dc0cb1cdSDale Ghent 		if (pba_block_size > max_pba_block_size)
829dc0cb1cdSDale Ghent 			return IXGBE_ERR_PARAM;
830dc0cb1cdSDale Ghent 
831dc0cb1cdSDale Ghent 		if (eeprom_buf == NULL) {
832dc0cb1cdSDale Ghent 			ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1],
833dc0cb1cdSDale Ghent 							     pba_block_size,
834dc0cb1cdSDale Ghent 							     pba->pba_block);
835dc0cb1cdSDale Ghent 			if (ret_val)
836dc0cb1cdSDale Ghent 				return ret_val;
837dc0cb1cdSDale Ghent 		} else {
838dc0cb1cdSDale Ghent 			if (eeprom_buf_size > (u32)(pba->word[1] +
839dc0cb1cdSDale Ghent 					      pba_block_size)) {
840dc0cb1cdSDale Ghent 				memcpy(pba->pba_block,
841dc0cb1cdSDale Ghent 				       &eeprom_buf[pba->word[1]],
842dc0cb1cdSDale Ghent 				       pba_block_size * sizeof(u16));
843dc0cb1cdSDale Ghent 			} else {
844dc0cb1cdSDale Ghent 				return IXGBE_ERR_PARAM;
845dc0cb1cdSDale Ghent 			}
846dc0cb1cdSDale Ghent 		}
847dc0cb1cdSDale Ghent 	}
848dc0cb1cdSDale Ghent 
849dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
850dc0cb1cdSDale Ghent }
851dc0cb1cdSDale Ghent 
852dc0cb1cdSDale Ghent /**
853dc0cb1cdSDale Ghent  *  ixgbe_write_pba_raw
854dc0cb1cdSDale Ghent  *  @hw: pointer to the HW structure
855dc0cb1cdSDale Ghent  *  @eeprom_buf: optional pointer to EEPROM image
856dc0cb1cdSDale Ghent  *  @eeprom_buf_size: size of EEPROM image in words
857dc0cb1cdSDale Ghent  *  @pba: pointer to PBA structure
858dc0cb1cdSDale Ghent  *
859dc0cb1cdSDale Ghent  *  Writes PBA to EEPROM image when eeprom_buf is not NULL.
860dc0cb1cdSDale Ghent  *  Writes PBA to physical EEPROM device when eeprom_buf is NULL.
861dc0cb1cdSDale Ghent  *
862dc0cb1cdSDale Ghent  **/
ixgbe_write_pba_raw(struct ixgbe_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,struct ixgbe_pba * pba)863dc0cb1cdSDale Ghent s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf,
864dc0cb1cdSDale Ghent 			u32 eeprom_buf_size, struct ixgbe_pba *pba)
865dc0cb1cdSDale Ghent {
866dc0cb1cdSDale Ghent 	s32 ret_val;
867dc0cb1cdSDale Ghent 
868dc0cb1cdSDale Ghent 	if (pba == NULL)
869dc0cb1cdSDale Ghent 		return IXGBE_ERR_PARAM;
870dc0cb1cdSDale Ghent 
871dc0cb1cdSDale Ghent 	if (eeprom_buf == NULL) {
872dc0cb1cdSDale Ghent 		ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2,
873dc0cb1cdSDale Ghent 						      &pba->word[0]);
874dc0cb1cdSDale Ghent 		if (ret_val)
875dc0cb1cdSDale Ghent 			return ret_val;
876dc0cb1cdSDale Ghent 	} else {
877dc0cb1cdSDale Ghent 		if (eeprom_buf_size > IXGBE_PBANUM1_PTR) {
878dc0cb1cdSDale Ghent 			eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0];
879dc0cb1cdSDale Ghent 			eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1];
880dc0cb1cdSDale Ghent 		} else {
881dc0cb1cdSDale Ghent 			return IXGBE_ERR_PARAM;
882dc0cb1cdSDale Ghent 		}
883dc0cb1cdSDale Ghent 	}
884dc0cb1cdSDale Ghent 
885dc0cb1cdSDale Ghent 	if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) {
886dc0cb1cdSDale Ghent 		if (pba->pba_block == NULL)
887dc0cb1cdSDale Ghent 			return IXGBE_ERR_PARAM;
888dc0cb1cdSDale Ghent 
889dc0cb1cdSDale Ghent 		if (eeprom_buf == NULL) {
890dc0cb1cdSDale Ghent 			ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1],
891dc0cb1cdSDale Ghent 							      pba->pba_block[0],
892dc0cb1cdSDale Ghent 							      pba->pba_block);
893dc0cb1cdSDale Ghent 			if (ret_val)
894dc0cb1cdSDale Ghent 				return ret_val;
895dc0cb1cdSDale Ghent 		} else {
896dc0cb1cdSDale Ghent 			if (eeprom_buf_size > (u32)(pba->word[1] +
897dc0cb1cdSDale Ghent 					      pba->pba_block[0])) {
898dc0cb1cdSDale Ghent 				memcpy(&eeprom_buf[pba->word[1]],
899dc0cb1cdSDale Ghent 				       pba->pba_block,
900dc0cb1cdSDale Ghent 				       pba->pba_block[0] * sizeof(u16));
901dc0cb1cdSDale Ghent 			} else {
902dc0cb1cdSDale Ghent 				return IXGBE_ERR_PARAM;
903dc0cb1cdSDale Ghent 			}
904dc0cb1cdSDale Ghent 		}
905dc0cb1cdSDale Ghent 	}
906dc0cb1cdSDale Ghent 
907dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
908dc0cb1cdSDale Ghent }
909dc0cb1cdSDale Ghent 
910dc0cb1cdSDale Ghent /**
911dc0cb1cdSDale Ghent  *  ixgbe_get_pba_block_size
912dc0cb1cdSDale Ghent  *  @hw: pointer to the HW structure
913dc0cb1cdSDale Ghent  *  @eeprom_buf: optional pointer to EEPROM image
914dc0cb1cdSDale Ghent  *  @eeprom_buf_size: size of EEPROM image in words
915dc0cb1cdSDale Ghent  *  @pba_data_size: pointer to output variable
916dc0cb1cdSDale Ghent  *
917dc0cb1cdSDale Ghent  *  Returns the size of the PBA block in words. Function operates on EEPROM
918dc0cb1cdSDale Ghent  *  image if the eeprom_buf pointer is not NULL otherwise it accesses physical
919dc0cb1cdSDale Ghent  *  EEPROM device.
920dc0cb1cdSDale Ghent  *
921dc0cb1cdSDale Ghent  **/
ixgbe_get_pba_block_size(struct ixgbe_hw * hw,u16 * eeprom_buf,u32 eeprom_buf_size,u16 * pba_block_size)922dc0cb1cdSDale Ghent s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf,
923dc0cb1cdSDale Ghent 			     u32 eeprom_buf_size, u16 *pba_block_size)
924dc0cb1cdSDale Ghent {
925dc0cb1cdSDale Ghent 	s32 ret_val;
926dc0cb1cdSDale Ghent 	u16 pba_word[2];
927dc0cb1cdSDale Ghent 	u16 length;
928dc0cb1cdSDale Ghent 
929dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_get_pba_block_size");
930dc0cb1cdSDale Ghent 
931dc0cb1cdSDale Ghent 	if (eeprom_buf == NULL) {
932dc0cb1cdSDale Ghent 		ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2,
933dc0cb1cdSDale Ghent 						     &pba_word[0]);
934dc0cb1cdSDale Ghent 		if (ret_val)
935dc0cb1cdSDale Ghent 			return ret_val;
936dc0cb1cdSDale Ghent 	} else {
937dc0cb1cdSDale Ghent 		if (eeprom_buf_size > IXGBE_PBANUM1_PTR) {
938dc0cb1cdSDale Ghent 			pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR];
939dc0cb1cdSDale Ghent 			pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR];
940dc0cb1cdSDale Ghent 		} else {
941dc0cb1cdSDale Ghent 			return IXGBE_ERR_PARAM;
942dc0cb1cdSDale Ghent 		}
943dc0cb1cdSDale Ghent 	}
944dc0cb1cdSDale Ghent 
945dc0cb1cdSDale Ghent 	if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) {
946dc0cb1cdSDale Ghent 		if (eeprom_buf == NULL) {
947dc0cb1cdSDale Ghent 			ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0,
948dc0cb1cdSDale Ghent 						      &length);
949dc0cb1cdSDale Ghent 			if (ret_val)
950dc0cb1cdSDale Ghent 				return ret_val;
951dc0cb1cdSDale Ghent 		} else {
952dc0cb1cdSDale Ghent 			if (eeprom_buf_size > pba_word[1])
953dc0cb1cdSDale Ghent 				length = eeprom_buf[pba_word[1] + 0];
954dc0cb1cdSDale Ghent 			else
955dc0cb1cdSDale Ghent 				return IXGBE_ERR_PARAM;
956dc0cb1cdSDale Ghent 		}
957dc0cb1cdSDale Ghent 
958dc0cb1cdSDale Ghent 		if (length == 0xFFFF || length == 0)
959dc0cb1cdSDale Ghent 			return IXGBE_ERR_PBA_SECTION;
960dc0cb1cdSDale Ghent 	} else {
961dc0cb1cdSDale Ghent 		/* PBA number in legacy format, there is no PBA Block. */
962dc0cb1cdSDale Ghent 		length = 0;
963dc0cb1cdSDale Ghent 	}
964dc0cb1cdSDale Ghent 
965dc0cb1cdSDale Ghent 	if (pba_block_size != NULL)
966dc0cb1cdSDale Ghent 		*pba_block_size = length;
967dc0cb1cdSDale Ghent 
968dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
969dc0cb1cdSDale Ghent }
970dc0cb1cdSDale Ghent 
97163b3bba8SJerry Jelinek /**
97263b3bba8SJerry Jelinek  *  ixgbe_get_mac_addr_generic - Generic get MAC address
97363b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
97463b3bba8SJerry Jelinek  *  @mac_addr: Adapter MAC address
9759da57d7bSbt  *
97663b3bba8SJerry Jelinek  *  Reads the adapter's MAC address from first Receive Address Register (RAR0)
97763b3bba8SJerry Jelinek  *  A reset of the adapter must be performed prior to calling this function
97863b3bba8SJerry Jelinek  *  in order for the MAC address to have been loaded from the EEPROM into RAR0
97963b3bba8SJerry Jelinek  **/
ixgbe_get_mac_addr_generic(struct ixgbe_hw * hw,u8 * mac_addr)98063b3bba8SJerry Jelinek s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
9819da57d7bSbt {
9829da57d7bSbt 	u32 rar_high;
9839da57d7bSbt 	u32 rar_low;
9849da57d7bSbt 	u16 i;
9859da57d7bSbt 
9863cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_mac_addr_generic");
9873cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
9889da57d7bSbt 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0));
9899da57d7bSbt 	rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0));
9909da57d7bSbt 
9919da57d7bSbt 	for (i = 0; i < 4; i++)
9929da57d7bSbt 		mac_addr[i] = (u8)(rar_low >> (i*8));
9939da57d7bSbt 
9949da57d7bSbt 	for (i = 0; i < 2; i++)
9959da57d7bSbt 		mac_addr[i+4] = (u8)(rar_high >> (i*8));
9969da57d7bSbt 
99763b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
9989da57d7bSbt }
9999da57d7bSbt 
100063b3bba8SJerry Jelinek /**
1001dc0cb1cdSDale Ghent  *  ixgbe_set_pci_config_data_generic - Generic store PCI bus info
100263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
1003dc0cb1cdSDale Ghent  *  @link_status: the link status returned by the PCI config space
10049da57d7bSbt  *
1005dc0cb1cdSDale Ghent  *  Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure
100663b3bba8SJerry Jelinek  **/
ixgbe_set_pci_config_data_generic(struct ixgbe_hw * hw,u16 link_status)1007dc0cb1cdSDale Ghent void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status)
10089da57d7bSbt {
100973cd555cSBin Tu - Sun Microsystems - Beijing China 	struct ixgbe_mac_info *mac = &hw->mac;
10109da57d7bSbt 
1011dc0cb1cdSDale Ghent 	if (hw->bus.type == ixgbe_bus_type_unknown)
1012dc0cb1cdSDale Ghent 		hw->bus.type = ixgbe_bus_type_pci_express;
10139da57d7bSbt 
10149da57d7bSbt 	switch (link_status & IXGBE_PCI_LINK_WIDTH) {
10159da57d7bSbt 	case IXGBE_PCI_LINK_WIDTH_1:
10169da57d7bSbt 		hw->bus.width = ixgbe_bus_width_pcie_x1;
10179da57d7bSbt 		break;
10189da57d7bSbt 	case IXGBE_PCI_LINK_WIDTH_2:
10199da57d7bSbt 		hw->bus.width = ixgbe_bus_width_pcie_x2;
10209da57d7bSbt 		break;
10219da57d7bSbt 	case IXGBE_PCI_LINK_WIDTH_4:
10229da57d7bSbt 		hw->bus.width = ixgbe_bus_width_pcie_x4;
10239da57d7bSbt 		break;
10249da57d7bSbt 	case IXGBE_PCI_LINK_WIDTH_8:
10259da57d7bSbt 		hw->bus.width = ixgbe_bus_width_pcie_x8;
10269da57d7bSbt 		break;
10279da57d7bSbt 	default:
10289da57d7bSbt 		hw->bus.width = ixgbe_bus_width_unknown;
10299da57d7bSbt 		break;
10309da57d7bSbt 	}
10319da57d7bSbt 
10329da57d7bSbt 	switch (link_status & IXGBE_PCI_LINK_SPEED) {
10339da57d7bSbt 	case IXGBE_PCI_LINK_SPEED_2500:
10349da57d7bSbt 		hw->bus.speed = ixgbe_bus_speed_2500;
10359da57d7bSbt 		break;
10369da57d7bSbt 	case IXGBE_PCI_LINK_SPEED_5000:
10379da57d7bSbt 		hw->bus.speed = ixgbe_bus_speed_5000;
10389da57d7bSbt 		break;
103969b5a878SDan McDonald 	case IXGBE_PCI_LINK_SPEED_8000:
104069b5a878SDan McDonald 		hw->bus.speed = ixgbe_bus_speed_8000;
104169b5a878SDan McDonald 		break;
10429da57d7bSbt 	default:
10439da57d7bSbt 		hw->bus.speed = ixgbe_bus_speed_unknown;
10449da57d7bSbt 		break;
10459da57d7bSbt 	}
10469da57d7bSbt 
104773cd555cSBin Tu - Sun Microsystems - Beijing China 	mac->ops.set_lan_id(hw);
1048dc0cb1cdSDale Ghent }
1049dc0cb1cdSDale Ghent 
1050dc0cb1cdSDale Ghent /**
1051dc0cb1cdSDale Ghent  *  ixgbe_get_bus_info_generic - Generic set PCI bus info
1052dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
1053dc0cb1cdSDale Ghent  *
1054dc0cb1cdSDale Ghent  *  Gets the PCI bus info (speed, width, type) then calls helper function to
1055dc0cb1cdSDale Ghent  *  store this data within the ixgbe_hw structure.
1056dc0cb1cdSDale Ghent  **/
ixgbe_get_bus_info_generic(struct ixgbe_hw * hw)1057dc0cb1cdSDale Ghent s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
1058dc0cb1cdSDale Ghent {
1059dc0cb1cdSDale Ghent 	u16 link_status;
1060dc0cb1cdSDale Ghent 
1061dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_get_bus_info_generic");
1062dc0cb1cdSDale Ghent 
1063dc0cb1cdSDale Ghent 	/* Get the negotiated link width and speed from PCI config space */
1064dc0cb1cdSDale Ghent 	link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS);
1065dc0cb1cdSDale Ghent 
1066dc0cb1cdSDale Ghent 	ixgbe_set_pci_config_data_generic(hw, link_status);
106773cd555cSBin Tu - Sun Microsystems - Beijing China 
106863b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
10699da57d7bSbt }
10709da57d7bSbt 
107163b3bba8SJerry Jelinek /**
107263b3bba8SJerry Jelinek  *  ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
107363b3bba8SJerry Jelinek  *  @hw: pointer to the HW structure
107473cd555cSBin Tu - Sun Microsystems - Beijing China  *
1075*48ed61a7SRobert Mustacchi  *  Determines the LAN function id by reading memory-mapped registers and swaps
1076*48ed61a7SRobert Mustacchi  *  the port value if requested, and set MAC instance for devices that share
1077*48ed61a7SRobert Mustacchi  *  CS4227.
107863b3bba8SJerry Jelinek  **/
ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw * hw)107963b3bba8SJerry Jelinek void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
108073cd555cSBin Tu - Sun Microsystems - Beijing China {
108173cd555cSBin Tu - Sun Microsystems - Beijing China 	struct ixgbe_bus_info *bus = &hw->bus;
108273cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 reg;
1083*48ed61a7SRobert Mustacchi 	u16 ee_ctrl_4;
108473cd555cSBin Tu - Sun Microsystems - Beijing China 
10853cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
10863cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
108773cd555cSBin Tu - Sun Microsystems - Beijing China 	reg = IXGBE_READ_REG(hw, IXGBE_STATUS);
108873cd555cSBin Tu - Sun Microsystems - Beijing China 	bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT;
1089*48ed61a7SRobert Mustacchi 	bus->lan_id = (u8)bus->func;
109073cd555cSBin Tu - Sun Microsystems - Beijing China 
109173cd555cSBin Tu - Sun Microsystems - Beijing China 	/* check for a port swap */
1092dc0cb1cdSDale Ghent 	reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
109373cd555cSBin Tu - Sun Microsystems - Beijing China 	if (reg & IXGBE_FACTPS_LFS)
109473cd555cSBin Tu - Sun Microsystems - Beijing China 		bus->func ^= 0x1;
1095*48ed61a7SRobert Mustacchi 
1096*48ed61a7SRobert Mustacchi 	/* Get MAC instance from EEPROM for configuring CS4227 */
1097*48ed61a7SRobert Mustacchi 	if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) {
1098*48ed61a7SRobert Mustacchi 		hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4);
1099*48ed61a7SRobert Mustacchi 		bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >>
1100*48ed61a7SRobert Mustacchi 				   IXGBE_EE_CTRL_4_INST_ID_SHIFT;
1101*48ed61a7SRobert Mustacchi 	}
110273cd555cSBin Tu - Sun Microsystems - Beijing China }
110373cd555cSBin Tu - Sun Microsystems - Beijing China 
110463b3bba8SJerry Jelinek /**
110563b3bba8SJerry Jelinek  *  ixgbe_stop_adapter_generic - Generic stop Tx/Rx units
110663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
11079da57d7bSbt  *
110863b3bba8SJerry Jelinek  *  Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
110963b3bba8SJerry Jelinek  *  disables transmit and receive units. The adapter_stopped flag is used by
111063b3bba8SJerry Jelinek  *  the shared code and drivers to determine if the adapter is in a stopped
111163b3bba8SJerry Jelinek  *  state and should not touch the hardware.
111263b3bba8SJerry Jelinek  **/
ixgbe_stop_adapter_generic(struct ixgbe_hw * hw)111363b3bba8SJerry Jelinek s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
11149da57d7bSbt {
11159da57d7bSbt 	u32 reg_val;
11169da57d7bSbt 	u16 i;
11179da57d7bSbt 
11183cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_stop_adapter_generic");
11193cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
11209da57d7bSbt 	/*
11219da57d7bSbt 	 * Set the adapter_stopped flag so other driver functions stop touching
11229da57d7bSbt 	 * the hardware
11239da57d7bSbt 	 */
112463b3bba8SJerry Jelinek 	hw->adapter_stopped = TRUE;
11259da57d7bSbt 
11269da57d7bSbt 	/* Disable the receive unit */
1127dc0cb1cdSDale Ghent 	ixgbe_disable_rx(hw);
11289da57d7bSbt 
112969b5a878SDan McDonald 	/* Clear interrupt mask to stop interrupts from being generated */
11309da57d7bSbt 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
11319da57d7bSbt 
113269b5a878SDan McDonald 	/* Clear any pending interrupts, flush previous writes */
1133dc0cb1cdSDale Ghent 	IXGBE_READ_REG(hw, IXGBE_EICR);
11349da57d7bSbt 
11359da57d7bSbt 	/* Disable the transmit unit.  Each queue must be disabled. */
113669b5a878SDan McDonald 	for (i = 0; i < hw->mac.max_tx_queues; i++)
113769b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH);
113869b5a878SDan McDonald 
113969b5a878SDan McDonald 	/* Disable the receive unit by stopping each queue */
114069b5a878SDan McDonald 	for (i = 0; i < hw->mac.max_rx_queues; i++) {
114169b5a878SDan McDonald 		reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
114269b5a878SDan McDonald 		reg_val &= ~IXGBE_RXDCTL_ENABLE;
114369b5a878SDan McDonald 		reg_val |= IXGBE_RXDCTL_SWFLSH;
114469b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
11459da57d7bSbt 	}
11469da57d7bSbt 
114769b5a878SDan McDonald 	/* flush all queues disables */
114869b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
114969b5a878SDan McDonald 	msec_delay(2);
115069b5a878SDan McDonald 
11519da57d7bSbt 	/*
1152dc0cb1cdSDale Ghent 	 * Prevent the PCI-E bus from hanging by disabling PCI-E master
11539da57d7bSbt 	 * access and verify no pending requests
11549da57d7bSbt 	 */
115569b5a878SDan McDonald 	return ixgbe_disable_pcie_master(hw);
11569da57d7bSbt }
11579da57d7bSbt 
1158*48ed61a7SRobert Mustacchi /**
1159*48ed61a7SRobert Mustacchi  *  ixgbe_init_led_link_act_generic - Store the LED index link/activity.
1160*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
1161*48ed61a7SRobert Mustacchi  *
1162*48ed61a7SRobert Mustacchi  *  Store the index for the link active LED. This will be used to support
1163*48ed61a7SRobert Mustacchi  *  blinking the LED.
1164*48ed61a7SRobert Mustacchi  **/
ixgbe_init_led_link_act_generic(struct ixgbe_hw * hw)1165*48ed61a7SRobert Mustacchi s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw)
1166*48ed61a7SRobert Mustacchi {
1167*48ed61a7SRobert Mustacchi 	struct ixgbe_mac_info *mac = &hw->mac;
1168*48ed61a7SRobert Mustacchi 	u32 led_reg, led_mode;
1169*48ed61a7SRobert Mustacchi 	u8 i;
1170*48ed61a7SRobert Mustacchi 
1171*48ed61a7SRobert Mustacchi 	led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
1172*48ed61a7SRobert Mustacchi 
1173*48ed61a7SRobert Mustacchi 	/* Get LED link active from the LEDCTL register */
1174*48ed61a7SRobert Mustacchi 	for (i = 0; i < 4; i++) {
1175*48ed61a7SRobert Mustacchi 		led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i);
1176*48ed61a7SRobert Mustacchi 
1177*48ed61a7SRobert Mustacchi 		if ((led_mode & IXGBE_LED_MODE_MASK_BASE) ==
1178*48ed61a7SRobert Mustacchi 		     IXGBE_LED_LINK_ACTIVE) {
1179*48ed61a7SRobert Mustacchi 			mac->led_link_act = i;
1180*48ed61a7SRobert Mustacchi 			return IXGBE_SUCCESS;
1181*48ed61a7SRobert Mustacchi 		}
1182*48ed61a7SRobert Mustacchi 	}
1183*48ed61a7SRobert Mustacchi 
1184*48ed61a7SRobert Mustacchi 	/*
1185*48ed61a7SRobert Mustacchi 	 * If LEDCTL register does not have the LED link active set, then use
1186*48ed61a7SRobert Mustacchi 	 * known MAC defaults.
1187*48ed61a7SRobert Mustacchi 	 */
1188*48ed61a7SRobert Mustacchi 	switch (hw->mac.type) {
1189*48ed61a7SRobert Mustacchi 	case ixgbe_mac_X550EM_a:
1190*48ed61a7SRobert Mustacchi 	case ixgbe_mac_X550EM_x:
1191*48ed61a7SRobert Mustacchi 		mac->led_link_act = 1;
1192*48ed61a7SRobert Mustacchi 		break;
1193*48ed61a7SRobert Mustacchi 	default:
1194*48ed61a7SRobert Mustacchi 		mac->led_link_act = 2;
1195*48ed61a7SRobert Mustacchi 	}
1196*48ed61a7SRobert Mustacchi 	return IXGBE_SUCCESS;
1197*48ed61a7SRobert Mustacchi }
1198*48ed61a7SRobert Mustacchi 
119963b3bba8SJerry Jelinek /**
120063b3bba8SJerry Jelinek  *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
120163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
120263b3bba8SJerry Jelinek  *  @index: led number to turn on
120363b3bba8SJerry Jelinek  **/
ixgbe_led_on_generic(struct ixgbe_hw * hw,u32 index)120463b3bba8SJerry Jelinek s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
12059da57d7bSbt {
12069da57d7bSbt 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
12079da57d7bSbt 
12083cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_led_on_generic");
12093cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
1210*48ed61a7SRobert Mustacchi 	if (index > 3)
1211*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_PARAM;
1212*48ed61a7SRobert Mustacchi 
12139da57d7bSbt 	/* To turn on the LED, set mode to ON. */
12149da57d7bSbt 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
12159da57d7bSbt 	led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index);
12169da57d7bSbt 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
12179da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
12189da57d7bSbt 
121963b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
12209da57d7bSbt }
12219da57d7bSbt 
122263b3bba8SJerry Jelinek /**
122363b3bba8SJerry Jelinek  *  ixgbe_led_off_generic - Turns off the software controllable LEDs.
122463b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
122563b3bba8SJerry Jelinek  *  @index: led number to turn off
122663b3bba8SJerry Jelinek  **/
ixgbe_led_off_generic(struct ixgbe_hw * hw,u32 index)122763b3bba8SJerry Jelinek s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
12289da57d7bSbt {
12299da57d7bSbt 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
12309da57d7bSbt 
12313cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_led_off_generic");
12323cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
1233*48ed61a7SRobert Mustacchi 	if (index > 3)
1234*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_PARAM;
1235*48ed61a7SRobert Mustacchi 
12369da57d7bSbt 	/* To turn off the LED, set mode to OFF. */
12379da57d7bSbt 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
12389da57d7bSbt 	led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index);
12399da57d7bSbt 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
12409da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
12419da57d7bSbt 
124263b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
12439da57d7bSbt }
12449da57d7bSbt 
124563b3bba8SJerry Jelinek /**
124663b3bba8SJerry Jelinek  *  ixgbe_init_eeprom_params_generic - Initialize EEPROM params
124763b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
12489da57d7bSbt  *
124963b3bba8SJerry Jelinek  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
125063b3bba8SJerry Jelinek  *  ixgbe_hw struct in order to set up EEPROM access.
125163b3bba8SJerry Jelinek  **/
ixgbe_init_eeprom_params_generic(struct ixgbe_hw * hw)125263b3bba8SJerry Jelinek s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
12539da57d7bSbt {
12549da57d7bSbt 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
12559da57d7bSbt 	u32 eec;
12569da57d7bSbt 	u16 eeprom_size;
12579da57d7bSbt 
12583cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_init_eeprom_params_generic");
12593cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
12609da57d7bSbt 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
12619da57d7bSbt 		eeprom->type = ixgbe_eeprom_none;
126263b3bba8SJerry Jelinek 		/* Set default semaphore delay to 10ms which is a well
126363b3bba8SJerry Jelinek 		 * tested value */
126413740cb2SPaul Guo 		eeprom->semaphore_delay = 10;
126569b5a878SDan McDonald 		/* Clear EEPROM page size, it will be initialized as needed */
126669b5a878SDan McDonald 		eeprom->word_page_size = 0;
12679da57d7bSbt 
12689da57d7bSbt 		/*
12699da57d7bSbt 		 * Check for EEPROM present first.
12709da57d7bSbt 		 * If not present leave as none
12719da57d7bSbt 		 */
1272dc0cb1cdSDale Ghent 		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
12739da57d7bSbt 		if (eec & IXGBE_EEC_PRES) {
12749da57d7bSbt 			eeprom->type = ixgbe_eeprom_spi;
12759da57d7bSbt 
12769da57d7bSbt 			/*
12779da57d7bSbt 			 * SPI EEPROM is assumed here.  This code would need to
12789da57d7bSbt 			 * change if a future EEPROM is not SPI.
12799da57d7bSbt 			 */
12809da57d7bSbt 			eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
128169b5a878SDan McDonald 					    IXGBE_EEC_SIZE_SHIFT);
12829da57d7bSbt 			eeprom->word_size = 1 << (eeprom_size +
128369b5a878SDan McDonald 					     IXGBE_EEPROM_WORD_SIZE_SHIFT);
12849da57d7bSbt 		}
12859da57d7bSbt 
12869da57d7bSbt 		if (eec & IXGBE_EEC_ADDR_SIZE)
12879da57d7bSbt 			eeprom->address_bits = 16;
12889da57d7bSbt 		else
12899da57d7bSbt 			eeprom->address_bits = 8;
12909da57d7bSbt 		DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: "
129169b5a878SDan McDonald 			  "%d\n", eeprom->type, eeprom->word_size,
129269b5a878SDan McDonald 			  eeprom->address_bits);
12939da57d7bSbt 	}
12949da57d7bSbt 
129563b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
12969da57d7bSbt }
12979da57d7bSbt 
129863b3bba8SJerry Jelinek /**
129969b5a878SDan McDonald  *  ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang
130063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
130169b5a878SDan McDonald  *  @offset: offset within the EEPROM to write
130269b5a878SDan McDonald  *  @words: number of word(s)
130369b5a878SDan McDonald  *  @data: 16 bit word(s) to write to EEPROM
13049da57d7bSbt  *
130569b5a878SDan McDonald  *  Reads 16 bit word(s) from EEPROM through bit-bang method
130663b3bba8SJerry Jelinek  **/
ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)130769b5a878SDan McDonald s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
130869b5a878SDan McDonald 					       u16 words, u16 *data)
13099da57d7bSbt {
131069b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
131169b5a878SDan McDonald 	u16 i, count;
13129da57d7bSbt 
131369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic");
13143cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
13159da57d7bSbt 	hw->eeprom.ops.init_params(hw);
13169da57d7bSbt 
131769b5a878SDan McDonald 	if (words == 0) {
131869b5a878SDan McDonald 		status = IXGBE_ERR_INVALID_ARGUMENT;
13199da57d7bSbt 		goto out;
13209da57d7bSbt 	}
13219da57d7bSbt 
132269b5a878SDan McDonald 	if (offset + words > hw->eeprom.word_size) {
132369b5a878SDan McDonald 		status = IXGBE_ERR_EEPROM;
132469b5a878SDan McDonald 		goto out;
13259da57d7bSbt 	}
13269da57d7bSbt 
132769b5a878SDan McDonald 	/*
132869b5a878SDan McDonald 	 * The EEPROM page size cannot be queried from the chip. We do lazy
132969b5a878SDan McDonald 	 * initialization. It is worth to do that when we write large buffer.
133069b5a878SDan McDonald 	 */
133169b5a878SDan McDonald 	if ((hw->eeprom.word_page_size == 0) &&
133269b5a878SDan McDonald 	    (words > IXGBE_EEPROM_PAGE_SIZE_MAX))
1333dc0cb1cdSDale Ghent 		ixgbe_detect_eeprom_page_size_generic(hw, offset);
13349da57d7bSbt 
133569b5a878SDan McDonald 	/*
133669b5a878SDan McDonald 	 * We cannot hold synchronization semaphores for too long
133769b5a878SDan McDonald 	 * to avoid other entity starvation. However it is more efficient
133869b5a878SDan McDonald 	 * to read in bursts than synchronizing access for each word.
133969b5a878SDan McDonald 	 */
134069b5a878SDan McDonald 	for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) {
134169b5a878SDan McDonald 		count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ?
134269b5a878SDan McDonald 			IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i);
134369b5a878SDan McDonald 		status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i,
134469b5a878SDan McDonald 							    count, &data[i]);
13459da57d7bSbt 
134669b5a878SDan McDonald 		if (status != IXGBE_SUCCESS)
134769b5a878SDan McDonald 			break;
134869b5a878SDan McDonald 	}
13499da57d7bSbt 
135069b5a878SDan McDonald out:
135169b5a878SDan McDonald 	return status;
135269b5a878SDan McDonald }
135369b5a878SDan McDonald 
135469b5a878SDan McDonald /**
135569b5a878SDan McDonald  *  ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM
135669b5a878SDan McDonald  *  @hw: pointer to hardware structure
135769b5a878SDan McDonald  *  @offset: offset within the EEPROM to be written to
135869b5a878SDan McDonald  *  @words: number of word(s)
135969b5a878SDan McDonald  *  @data: 16 bit word(s) to be written to the EEPROM
136069b5a878SDan McDonald  *
136169b5a878SDan McDonald  *  If ixgbe_eeprom_update_checksum is not called after this function, the
136269b5a878SDan McDonald  *  EEPROM will most likely contain an invalid checksum.
136369b5a878SDan McDonald  **/
ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)136469b5a878SDan McDonald static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
136569b5a878SDan McDonald 					      u16 words, u16 *data)
136669b5a878SDan McDonald {
136769b5a878SDan McDonald 	s32 status;
136869b5a878SDan McDonald 	u16 word;
136969b5a878SDan McDonald 	u16 page_size;
137069b5a878SDan McDonald 	u16 i;
137169b5a878SDan McDonald 	u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
137269b5a878SDan McDonald 
137369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang");
137469b5a878SDan McDonald 
137569b5a878SDan McDonald 	/* Prepare the EEPROM for writing  */
137669b5a878SDan McDonald 	status = ixgbe_acquire_eeprom(hw);
137769b5a878SDan McDonald 
137869b5a878SDan McDonald 	if (status == IXGBE_SUCCESS) {
137969b5a878SDan McDonald 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
138069b5a878SDan McDonald 			ixgbe_release_eeprom(hw);
138169b5a878SDan McDonald 			status = IXGBE_ERR_EEPROM;
138269b5a878SDan McDonald 		}
138369b5a878SDan McDonald 	}
138469b5a878SDan McDonald 
138569b5a878SDan McDonald 	if (status == IXGBE_SUCCESS) {
138669b5a878SDan McDonald 		for (i = 0; i < words; i++) {
138769b5a878SDan McDonald 			ixgbe_standby_eeprom(hw);
138869b5a878SDan McDonald 
138969b5a878SDan McDonald 			/*  Send the WRITE ENABLE command (8 bit opcode )  */
139069b5a878SDan McDonald 			ixgbe_shift_out_eeprom_bits(hw,
139169b5a878SDan McDonald 						   IXGBE_EEPROM_WREN_OPCODE_SPI,
139269b5a878SDan McDonald 						   IXGBE_EEPROM_OPCODE_BITS);
139369b5a878SDan McDonald 
139469b5a878SDan McDonald 			ixgbe_standby_eeprom(hw);
139569b5a878SDan McDonald 
139669b5a878SDan McDonald 			/*
139769b5a878SDan McDonald 			 * Some SPI eeproms use the 8th address bit embedded
139869b5a878SDan McDonald 			 * in the opcode
139969b5a878SDan McDonald 			 */
140069b5a878SDan McDonald 			if ((hw->eeprom.address_bits == 8) &&
140169b5a878SDan McDonald 			    ((offset + i) >= 128))
140269b5a878SDan McDonald 				write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
140369b5a878SDan McDonald 
140469b5a878SDan McDonald 			/* Send the Write command (8-bit opcode + addr) */
140569b5a878SDan McDonald 			ixgbe_shift_out_eeprom_bits(hw, write_opcode,
140669b5a878SDan McDonald 						    IXGBE_EEPROM_OPCODE_BITS);
140769b5a878SDan McDonald 			ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
140869b5a878SDan McDonald 						    hw->eeprom.address_bits);
140969b5a878SDan McDonald 
141069b5a878SDan McDonald 			page_size = hw->eeprom.word_page_size;
141169b5a878SDan McDonald 
141269b5a878SDan McDonald 			/* Send the data in burst via SPI*/
141369b5a878SDan McDonald 			do {
141469b5a878SDan McDonald 				word = data[i];
141569b5a878SDan McDonald 				word = (word >> 8) | (word << 8);
141669b5a878SDan McDonald 				ixgbe_shift_out_eeprom_bits(hw, word, 16);
141769b5a878SDan McDonald 
141869b5a878SDan McDonald 				if (page_size == 0)
141969b5a878SDan McDonald 					break;
142069b5a878SDan McDonald 
142169b5a878SDan McDonald 				/* do not wrap around page */
142269b5a878SDan McDonald 				if (((offset + i) & (page_size - 1)) ==
142369b5a878SDan McDonald 				    (page_size - 1))
142469b5a878SDan McDonald 					break;
142569b5a878SDan McDonald 			} while (++i < words);
142669b5a878SDan McDonald 
142769b5a878SDan McDonald 			ixgbe_standby_eeprom(hw);
142869b5a878SDan McDonald 			msec_delay(10);
142969b5a878SDan McDonald 		}
143069b5a878SDan McDonald 		/* Done with writing - release the EEPROM */
14319da57d7bSbt 		ixgbe_release_eeprom(hw);
14329da57d7bSbt 	}
14339da57d7bSbt 
143463b3bba8SJerry Jelinek 	return status;
14359da57d7bSbt }
14369da57d7bSbt 
143763b3bba8SJerry Jelinek /**
143869b5a878SDan McDonald  *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
143963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
144069b5a878SDan McDonald  *  @offset: offset within the EEPROM to be written to
144169b5a878SDan McDonald  *  @data: 16 bit word to be written to the EEPROM
14429da57d7bSbt  *
144369b5a878SDan McDonald  *  If ixgbe_eeprom_update_checksum is not called after this function, the
144469b5a878SDan McDonald  *  EEPROM will most likely contain an invalid checksum.
144563b3bba8SJerry Jelinek  **/
ixgbe_write_eeprom_generic(struct ixgbe_hw * hw,u16 offset,u16 data)144669b5a878SDan McDonald s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
14479da57d7bSbt {
14489da57d7bSbt 	s32 status;
14499da57d7bSbt 
145069b5a878SDan McDonald 	DEBUGFUNC("ixgbe_write_eeprom_generic");
14513cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
14529da57d7bSbt 	hw->eeprom.ops.init_params(hw);
14539da57d7bSbt 
14549da57d7bSbt 	if (offset >= hw->eeprom.word_size) {
14559da57d7bSbt 		status = IXGBE_ERR_EEPROM;
14569da57d7bSbt 		goto out;
14579da57d7bSbt 	}
14589da57d7bSbt 
145969b5a878SDan McDonald 	status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
146069b5a878SDan McDonald 
146169b5a878SDan McDonald out:
146269b5a878SDan McDonald 	return status;
146369b5a878SDan McDonald }
146469b5a878SDan McDonald 
146569b5a878SDan McDonald /**
146669b5a878SDan McDonald  *  ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang
146769b5a878SDan McDonald  *  @hw: pointer to hardware structure
146869b5a878SDan McDonald  *  @offset: offset within the EEPROM to be read
146969b5a878SDan McDonald  *  @data: read 16 bit words(s) from EEPROM
147069b5a878SDan McDonald  *  @words: number of word(s)
147169b5a878SDan McDonald  *
147269b5a878SDan McDonald  *  Reads 16 bit word(s) from EEPROM through bit-bang method
147369b5a878SDan McDonald  **/
ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)147469b5a878SDan McDonald s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
147569b5a878SDan McDonald 					      u16 words, u16 *data)
147669b5a878SDan McDonald {
147769b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
147869b5a878SDan McDonald 	u16 i, count;
147969b5a878SDan McDonald 
148069b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic");
148169b5a878SDan McDonald 
148269b5a878SDan McDonald 	hw->eeprom.ops.init_params(hw);
148369b5a878SDan McDonald 
148469b5a878SDan McDonald 	if (words == 0) {
148569b5a878SDan McDonald 		status = IXGBE_ERR_INVALID_ARGUMENT;
148669b5a878SDan McDonald 		goto out;
148769b5a878SDan McDonald 	}
148869b5a878SDan McDonald 
148969b5a878SDan McDonald 	if (offset + words > hw->eeprom.word_size) {
149069b5a878SDan McDonald 		status = IXGBE_ERR_EEPROM;
149169b5a878SDan McDonald 		goto out;
149269b5a878SDan McDonald 	}
149369b5a878SDan McDonald 
149469b5a878SDan McDonald 	/*
149569b5a878SDan McDonald 	 * We cannot hold synchronization semaphores for too long
149669b5a878SDan McDonald 	 * to avoid other entity starvation. However it is more efficient
149769b5a878SDan McDonald 	 * to read in bursts than synchronizing access for each word.
149869b5a878SDan McDonald 	 */
149969b5a878SDan McDonald 	for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) {
150069b5a878SDan McDonald 		count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ?
150169b5a878SDan McDonald 			IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i);
150269b5a878SDan McDonald 
150369b5a878SDan McDonald 		status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i,
150469b5a878SDan McDonald 							   count, &data[i]);
150569b5a878SDan McDonald 
150669b5a878SDan McDonald 		if (status != IXGBE_SUCCESS)
150769b5a878SDan McDonald 			break;
150869b5a878SDan McDonald 	}
150969b5a878SDan McDonald 
151069b5a878SDan McDonald out:
151169b5a878SDan McDonald 	return status;
151269b5a878SDan McDonald }
151369b5a878SDan McDonald 
151469b5a878SDan McDonald /**
151569b5a878SDan McDonald  *  ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang
151669b5a878SDan McDonald  *  @hw: pointer to hardware structure
151769b5a878SDan McDonald  *  @offset: offset within the EEPROM to be read
151869b5a878SDan McDonald  *  @words: number of word(s)
151969b5a878SDan McDonald  *  @data: read 16 bit word(s) from EEPROM
152069b5a878SDan McDonald  *
152169b5a878SDan McDonald  *  Reads 16 bit word(s) from EEPROM through bit-bang method
152269b5a878SDan McDonald  **/
ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)152369b5a878SDan McDonald static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
152469b5a878SDan McDonald 					     u16 words, u16 *data)
152569b5a878SDan McDonald {
152669b5a878SDan McDonald 	s32 status;
152769b5a878SDan McDonald 	u16 word_in;
152869b5a878SDan McDonald 	u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
152969b5a878SDan McDonald 	u16 i;
153069b5a878SDan McDonald 
153169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang");
153269b5a878SDan McDonald 
15339da57d7bSbt 	/* Prepare the EEPROM for reading  */
15349da57d7bSbt 	status = ixgbe_acquire_eeprom(hw);
15359da57d7bSbt 
15369da57d7bSbt 	if (status == IXGBE_SUCCESS) {
15379da57d7bSbt 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
15389da57d7bSbt 			ixgbe_release_eeprom(hw);
15399da57d7bSbt 			status = IXGBE_ERR_EEPROM;
15409da57d7bSbt 		}
15419da57d7bSbt 	}
15429da57d7bSbt 
15439da57d7bSbt 	if (status == IXGBE_SUCCESS) {
154469b5a878SDan McDonald 		for (i = 0; i < words; i++) {
154569b5a878SDan McDonald 			ixgbe_standby_eeprom(hw);
154669b5a878SDan McDonald 			/*
154769b5a878SDan McDonald 			 * Some SPI eeproms use the 8th address bit embedded
154869b5a878SDan McDonald 			 * in the opcode
154969b5a878SDan McDonald 			 */
155069b5a878SDan McDonald 			if ((hw->eeprom.address_bits == 8) &&
155169b5a878SDan McDonald 			    ((offset + i) >= 128))
155269b5a878SDan McDonald 				read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
155369b5a878SDan McDonald 
155469b5a878SDan McDonald 			/* Send the READ command (opcode + addr) */
155569b5a878SDan McDonald 			ixgbe_shift_out_eeprom_bits(hw, read_opcode,
155669b5a878SDan McDonald 						    IXGBE_EEPROM_OPCODE_BITS);
155769b5a878SDan McDonald 			ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
155869b5a878SDan McDonald 						    hw->eeprom.address_bits);
155969b5a878SDan McDonald 
156069b5a878SDan McDonald 			/* Read the data. */
156169b5a878SDan McDonald 			word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
156269b5a878SDan McDonald 			data[i] = (word_in >> 8) | (word_in << 8);
156369b5a878SDan McDonald 		}
15649da57d7bSbt 
156569b5a878SDan McDonald 		/* End this read operation */
156669b5a878SDan McDonald 		ixgbe_release_eeprom(hw);
156769b5a878SDan McDonald 	}
156869b5a878SDan McDonald 
156969b5a878SDan McDonald 	return status;
157069b5a878SDan McDonald }
157169b5a878SDan McDonald 
157269b5a878SDan McDonald /**
157369b5a878SDan McDonald  *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
157469b5a878SDan McDonald  *  @hw: pointer to hardware structure
157569b5a878SDan McDonald  *  @offset: offset within the EEPROM to be read
157669b5a878SDan McDonald  *  @data: read 16 bit value from EEPROM
157769b5a878SDan McDonald  *
157869b5a878SDan McDonald  *  Reads 16 bit value from EEPROM through bit-bang method
157969b5a878SDan McDonald  **/
ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw * hw,u16 offset,u16 * data)158069b5a878SDan McDonald s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
158169b5a878SDan McDonald 				       u16 *data)
158269b5a878SDan McDonald {
158369b5a878SDan McDonald 	s32 status;
15849da57d7bSbt 
158569b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic");
15869da57d7bSbt 
158769b5a878SDan McDonald 	hw->eeprom.ops.init_params(hw);
15889da57d7bSbt 
158969b5a878SDan McDonald 	if (offset >= hw->eeprom.word_size) {
159069b5a878SDan McDonald 		status = IXGBE_ERR_EEPROM;
159169b5a878SDan McDonald 		goto out;
15929da57d7bSbt 	}
15939da57d7bSbt 
159469b5a878SDan McDonald 	status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
159569b5a878SDan McDonald 
15969da57d7bSbt out:
159763b3bba8SJerry Jelinek 	return status;
15989da57d7bSbt }
15999da57d7bSbt 
160063b3bba8SJerry Jelinek /**
160169b5a878SDan McDonald  *  ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD
160263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
160369b5a878SDan McDonald  *  @offset: offset of word in the EEPROM to read
160469b5a878SDan McDonald  *  @words: number of word(s)
160569b5a878SDan McDonald  *  @data: 16 bit word(s) from the EEPROM
16069da57d7bSbt  *
160769b5a878SDan McDonald  *  Reads a 16 bit word(s) from the EEPROM using the EERD register.
160863b3bba8SJerry Jelinek  **/
ixgbe_read_eerd_buffer_generic(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)160969b5a878SDan McDonald s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset,
161069b5a878SDan McDonald 				   u16 words, u16 *data)
16119da57d7bSbt {
16129da57d7bSbt 	u32 eerd;
161369b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
161469b5a878SDan McDonald 	u32 i;
16159da57d7bSbt 
161669b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_eerd_buffer_generic");
16173cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
16189da57d7bSbt 	hw->eeprom.ops.init_params(hw);
16199da57d7bSbt 
162069b5a878SDan McDonald 	if (words == 0) {
162169b5a878SDan McDonald 		status = IXGBE_ERR_INVALID_ARGUMENT;
1622dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words");
162369b5a878SDan McDonald 		goto out;
162469b5a878SDan McDonald 	}
162569b5a878SDan McDonald 
16269da57d7bSbt 	if (offset >= hw->eeprom.word_size) {
16279da57d7bSbt 		status = IXGBE_ERR_EEPROM;
1628dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset");
16299da57d7bSbt 		goto out;
16309da57d7bSbt 	}
16319da57d7bSbt 
163269b5a878SDan McDonald 	for (i = 0; i < words; i++) {
1633dc0cb1cdSDale Ghent 		eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
163469b5a878SDan McDonald 		       IXGBE_EEPROM_RW_REG_START;
16359da57d7bSbt 
163669b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
163769b5a878SDan McDonald 		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
16389da57d7bSbt 
163969b5a878SDan McDonald 		if (status == IXGBE_SUCCESS) {
164069b5a878SDan McDonald 			data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
164169b5a878SDan McDonald 				   IXGBE_EEPROM_RW_REG_DATA);
164269b5a878SDan McDonald 		} else {
164369b5a878SDan McDonald 			DEBUGOUT("Eeprom read timed out\n");
164469b5a878SDan McDonald 			goto out;
164569b5a878SDan McDonald 		}
164669b5a878SDan McDonald 	}
164769b5a878SDan McDonald out:
164869b5a878SDan McDonald 	return status;
164969b5a878SDan McDonald }
165069b5a878SDan McDonald 
165169b5a878SDan McDonald /**
165269b5a878SDan McDonald  *  ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size
165369b5a878SDan McDonald  *  @hw: pointer to hardware structure
165469b5a878SDan McDonald  *  @offset: offset within the EEPROM to be used as a scratch pad
165569b5a878SDan McDonald  *
165669b5a878SDan McDonald  *  Discover EEPROM page size by writing marching data at given offset.
165769b5a878SDan McDonald  *  This function is called only when we are writing a new large buffer
165869b5a878SDan McDonald  *  at given offset so the data would be overwritten anyway.
165969b5a878SDan McDonald  **/
ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw * hw,u16 offset)166069b5a878SDan McDonald static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
166169b5a878SDan McDonald 						 u16 offset)
166269b5a878SDan McDonald {
166369b5a878SDan McDonald 	u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX];
166469b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
166569b5a878SDan McDonald 	u16 i;
166669b5a878SDan McDonald 
166769b5a878SDan McDonald 	DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic");
166869b5a878SDan McDonald 
166969b5a878SDan McDonald 	for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++)
167069b5a878SDan McDonald 		data[i] = i;
167169b5a878SDan McDonald 
167269b5a878SDan McDonald 	hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX;
167369b5a878SDan McDonald 	status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset,
167469b5a878SDan McDonald 					     IXGBE_EEPROM_PAGE_SIZE_MAX, data);
167569b5a878SDan McDonald 	hw->eeprom.word_page_size = 0;
167669b5a878SDan McDonald 	if (status != IXGBE_SUCCESS)
167769b5a878SDan McDonald 		goto out;
167869b5a878SDan McDonald 
167969b5a878SDan McDonald 	status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
168069b5a878SDan McDonald 	if (status != IXGBE_SUCCESS)
168169b5a878SDan McDonald 		goto out;
168269b5a878SDan McDonald 
168369b5a878SDan McDonald 	/*
168469b5a878SDan McDonald 	 * When writing in burst more than the actual page size
168569b5a878SDan McDonald 	 * EEPROM address wraps around current page.
168669b5a878SDan McDonald 	 */
168769b5a878SDan McDonald 	hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0];
16889da57d7bSbt 
168969b5a878SDan McDonald 	DEBUGOUT1("Detected EEPROM page size = %d words.",
169069b5a878SDan McDonald 		  hw->eeprom.word_page_size);
16919da57d7bSbt out:
169263b3bba8SJerry Jelinek 	return status;
169363b3bba8SJerry Jelinek }
169463b3bba8SJerry Jelinek 
169563b3bba8SJerry Jelinek /**
169669b5a878SDan McDonald  *  ixgbe_read_eerd_generic - Read EEPROM word using EERD
169769b5a878SDan McDonald  *  @hw: pointer to hardware structure
169869b5a878SDan McDonald  *  @offset: offset of  word in the EEPROM to read
169969b5a878SDan McDonald  *  @data: word read from the EEPROM
170069b5a878SDan McDonald  *
170169b5a878SDan McDonald  *  Reads a 16 bit word from the EEPROM using the EERD register.
170269b5a878SDan McDonald  **/
ixgbe_read_eerd_generic(struct ixgbe_hw * hw,u16 offset,u16 * data)170369b5a878SDan McDonald s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
170469b5a878SDan McDonald {
170569b5a878SDan McDonald 	return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data);
170669b5a878SDan McDonald }
170769b5a878SDan McDonald 
170869b5a878SDan McDonald /**
170969b5a878SDan McDonald  *  ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR
171063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
171163b3bba8SJerry Jelinek  *  @offset: offset of  word in the EEPROM to write
171269b5a878SDan McDonald  *  @words: number of word(s)
171369b5a878SDan McDonald  *  @data: word(s) write to the EEPROM
171463b3bba8SJerry Jelinek  *
171569b5a878SDan McDonald  *  Write a 16 bit word(s) to the EEPROM using the EEWR register.
171663b3bba8SJerry Jelinek  **/
ixgbe_write_eewr_buffer_generic(struct ixgbe_hw * hw,u16 offset,u16 words,u16 * data)171769b5a878SDan McDonald s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset,
171869b5a878SDan McDonald 				    u16 words, u16 *data)
171963b3bba8SJerry Jelinek {
172063b3bba8SJerry Jelinek 	u32 eewr;
172169b5a878SDan McDonald 	s32 status = IXGBE_SUCCESS;
172269b5a878SDan McDonald 	u16 i;
172363b3bba8SJerry Jelinek 
172463b3bba8SJerry Jelinek 	DEBUGFUNC("ixgbe_write_eewr_generic");
172563b3bba8SJerry Jelinek 
172663b3bba8SJerry Jelinek 	hw->eeprom.ops.init_params(hw);
172763b3bba8SJerry Jelinek 
172869b5a878SDan McDonald 	if (words == 0) {
172969b5a878SDan McDonald 		status = IXGBE_ERR_INVALID_ARGUMENT;
1730dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words");
173169b5a878SDan McDonald 		goto out;
173269b5a878SDan McDonald 	}
173369b5a878SDan McDonald 
173463b3bba8SJerry Jelinek 	if (offset >= hw->eeprom.word_size) {
173563b3bba8SJerry Jelinek 		status = IXGBE_ERR_EEPROM;
1736dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset");
173763b3bba8SJerry Jelinek 		goto out;
173863b3bba8SJerry Jelinek 	}
173963b3bba8SJerry Jelinek 
174069b5a878SDan McDonald 	for (i = 0; i < words; i++) {
174169b5a878SDan McDonald 		eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
174269b5a878SDan McDonald 			(data[i] << IXGBE_EEPROM_RW_REG_DATA) |
174369b5a878SDan McDonald 			IXGBE_EEPROM_RW_REG_START;
174463b3bba8SJerry Jelinek 
174569b5a878SDan McDonald 		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
174669b5a878SDan McDonald 		if (status != IXGBE_SUCCESS) {
174769b5a878SDan McDonald 			DEBUGOUT("Eeprom write EEWR timed out\n");
174869b5a878SDan McDonald 			goto out;
174969b5a878SDan McDonald 		}
175063b3bba8SJerry Jelinek 
175169b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
175263b3bba8SJerry Jelinek 
175369b5a878SDan McDonald 		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
175469b5a878SDan McDonald 		if (status != IXGBE_SUCCESS) {
175569b5a878SDan McDonald 			DEBUGOUT("Eeprom write EEWR timed out\n");
175669b5a878SDan McDonald 			goto out;
175769b5a878SDan McDonald 		}
175863b3bba8SJerry Jelinek 	}
175963b3bba8SJerry Jelinek 
176063b3bba8SJerry Jelinek out:
176163b3bba8SJerry Jelinek 	return status;
17629da57d7bSbt }
17639da57d7bSbt 
176469b5a878SDan McDonald /**
176569b5a878SDan McDonald  *  ixgbe_write_eewr_generic - Write EEPROM word using EEWR
176669b5a878SDan McDonald  *  @hw: pointer to hardware structure
176769b5a878SDan McDonald  *  @offset: offset of  word in the EEPROM to write
176869b5a878SDan McDonald  *  @data: word write to the EEPROM
176969b5a878SDan McDonald  *
177069b5a878SDan McDonald  *  Write a 16 bit word to the EEPROM using the EEWR register.
177169b5a878SDan McDonald  **/
ixgbe_write_eewr_generic(struct ixgbe_hw * hw,u16 offset,u16 data)177269b5a878SDan McDonald s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
177369b5a878SDan McDonald {
177469b5a878SDan McDonald 	return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data);
177569b5a878SDan McDonald }
177669b5a878SDan McDonald 
177763b3bba8SJerry Jelinek /**
177863b3bba8SJerry Jelinek  *  ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
177963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
178063b3bba8SJerry Jelinek  *  @ee_reg: EEPROM flag for polling
17819da57d7bSbt  *
178263b3bba8SJerry Jelinek  *  Polls the status bit (bit 1) of the EERD or EEWR to determine when the
178363b3bba8SJerry Jelinek  *  read or write is done respectively.
178463b3bba8SJerry Jelinek  **/
ixgbe_poll_eerd_eewr_done(struct ixgbe_hw * hw,u32 ee_reg)178563b3bba8SJerry Jelinek s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
17869da57d7bSbt {
17879da57d7bSbt 	u32 i;
17889da57d7bSbt 	u32 reg;
17899da57d7bSbt 	s32 status = IXGBE_ERR_EEPROM;
17909da57d7bSbt 
17913cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_poll_eerd_eewr_done");
17923cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
17933cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) {
17943cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		if (ee_reg == IXGBE_NVM_POLL_READ)
17953cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			reg = IXGBE_READ_REG(hw, IXGBE_EERD);
17963cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		else
17973cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			reg = IXGBE_READ_REG(hw, IXGBE_EEWR);
17983cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
17993cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		if (reg & IXGBE_EEPROM_RW_REG_DONE) {
18009da57d7bSbt 			status = IXGBE_SUCCESS;
18019da57d7bSbt 			break;
18029da57d7bSbt 		}
18039da57d7bSbt 		usec_delay(5);
18049da57d7bSbt 	}
1805dc0cb1cdSDale Ghent 
1806dc0cb1cdSDale Ghent 	if (i == IXGBE_EERD_EEWR_ATTEMPTS)
1807dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_POLLING,
1808dc0cb1cdSDale Ghent 			     "EEPROM read/write done polling timed out");
1809dc0cb1cdSDale Ghent 
181063b3bba8SJerry Jelinek 	return status;
18119da57d7bSbt }
18129da57d7bSbt 
181363b3bba8SJerry Jelinek /**
181463b3bba8SJerry Jelinek  *  ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang
181563b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
18169da57d7bSbt  *
181763b3bba8SJerry Jelinek  *  Prepares EEPROM for access using bit-bang method. This function should
181863b3bba8SJerry Jelinek  *  be called before issuing a command to the EEPROM.
181963b3bba8SJerry Jelinek  **/
ixgbe_acquire_eeprom(struct ixgbe_hw * hw)182063b3bba8SJerry Jelinek static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
18219da57d7bSbt {
18229da57d7bSbt 	s32 status = IXGBE_SUCCESS;
18239da57d7bSbt 	u32 eec;
18249da57d7bSbt 	u32 i;
18259da57d7bSbt 
18263cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_acquire_eeprom");
18273cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
182869b5a878SDan McDonald 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)
182969b5a878SDan McDonald 	    != IXGBE_SUCCESS)
18309da57d7bSbt 		status = IXGBE_ERR_SWFW_SYNC;
18319da57d7bSbt 
18329da57d7bSbt 	if (status == IXGBE_SUCCESS) {
1833dc0cb1cdSDale Ghent 		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
18349da57d7bSbt 
18359da57d7bSbt 		/* Request EEPROM Access */
18369da57d7bSbt 		eec |= IXGBE_EEC_REQ;
1837dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
18389da57d7bSbt 
18399da57d7bSbt 		for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
1840dc0cb1cdSDale Ghent 			eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
18419da57d7bSbt 			if (eec & IXGBE_EEC_GNT)
18429da57d7bSbt 				break;
18439da57d7bSbt 			usec_delay(5);
18449da57d7bSbt 		}
18459da57d7bSbt 
18469da57d7bSbt 		/* Release if grant not acquired */
18479da57d7bSbt 		if (!(eec & IXGBE_EEC_GNT)) {
18489da57d7bSbt 			eec &= ~IXGBE_EEC_REQ;
1849dc0cb1cdSDale Ghent 			IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
18509da57d7bSbt 			DEBUGOUT("Could not acquire EEPROM grant\n");
18519da57d7bSbt 
185269b5a878SDan McDonald 			hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
18539da57d7bSbt 			status = IXGBE_ERR_EEPROM;
18549da57d7bSbt 		}
18559da57d7bSbt 
185663b3bba8SJerry Jelinek 		/* Setup EEPROM for Read/Write */
185763b3bba8SJerry Jelinek 		if (status == IXGBE_SUCCESS) {
185863b3bba8SJerry Jelinek 			/* Clear CS and SK */
185963b3bba8SJerry Jelinek 			eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
1860dc0cb1cdSDale Ghent 			IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
186163b3bba8SJerry Jelinek 			IXGBE_WRITE_FLUSH(hw);
186263b3bba8SJerry Jelinek 			usec_delay(1);
186363b3bba8SJerry Jelinek 		}
18649da57d7bSbt 	}
186563b3bba8SJerry Jelinek 	return status;
18669da57d7bSbt }
18679da57d7bSbt 
186863b3bba8SJerry Jelinek /**
186963b3bba8SJerry Jelinek  *  ixgbe_get_eeprom_semaphore - Get hardware semaphore
187063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
18719da57d7bSbt  *
187263b3bba8SJerry Jelinek  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
187363b3bba8SJerry Jelinek  **/
ixgbe_get_eeprom_semaphore(struct ixgbe_hw * hw)187463b3bba8SJerry Jelinek static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
18759da57d7bSbt {
18769da57d7bSbt 	s32 status = IXGBE_ERR_EEPROM;
1877185c5677SPaul Guo 	u32 timeout = 2000;
18789da57d7bSbt 	u32 i;
18799da57d7bSbt 	u32 swsm;
18809da57d7bSbt 
18813cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_eeprom_semaphore");
18823cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
188363b3bba8SJerry Jelinek 
18849da57d7bSbt 	/* Get SMBI software semaphore between device drivers first */
18859da57d7bSbt 	for (i = 0; i < timeout; i++) {
18869da57d7bSbt 		/*
18879da57d7bSbt 		 * If the SMBI bit is 0 when we read it, then the bit will be
18889da57d7bSbt 		 * set and we have the semaphore
18899da57d7bSbt 		 */
1890dc0cb1cdSDale Ghent 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
18919da57d7bSbt 		if (!(swsm & IXGBE_SWSM_SMBI)) {
18929da57d7bSbt 			status = IXGBE_SUCCESS;
18939da57d7bSbt 			break;
18949da57d7bSbt 		}
1895185c5677SPaul Guo 		usec_delay(50);
18969da57d7bSbt 	}
18979da57d7bSbt 
189869b5a878SDan McDonald 	if (i == timeout) {
189969b5a878SDan McDonald 		DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore "
190069b5a878SDan McDonald 			 "not granted.\n");
190169b5a878SDan McDonald 		/*
190269b5a878SDan McDonald 		 * this release is particularly important because our attempts
190369b5a878SDan McDonald 		 * above to get the semaphore may have succeeded, and if there
190469b5a878SDan McDonald 		 * was a timeout, we should unconditionally clear the semaphore
190569b5a878SDan McDonald 		 * bits to free the driver to make progress
190669b5a878SDan McDonald 		 */
190769b5a878SDan McDonald 		ixgbe_release_eeprom_semaphore(hw);
190869b5a878SDan McDonald 
190969b5a878SDan McDonald 		usec_delay(50);
191069b5a878SDan McDonald 		/*
191169b5a878SDan McDonald 		 * one last try
191269b5a878SDan McDonald 		 * If the SMBI bit is 0 when we read it, then the bit will be
191369b5a878SDan McDonald 		 * set and we have the semaphore
191469b5a878SDan McDonald 		 */
1915dc0cb1cdSDale Ghent 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
191669b5a878SDan McDonald 		if (!(swsm & IXGBE_SWSM_SMBI))
191769b5a878SDan McDonald 			status = IXGBE_SUCCESS;
191869b5a878SDan McDonald 	}
191969b5a878SDan McDonald 
19209da57d7bSbt 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
19219da57d7bSbt 	if (status == IXGBE_SUCCESS) {
19229da57d7bSbt 		for (i = 0; i < timeout; i++) {
1923dc0cb1cdSDale Ghent 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
19249da57d7bSbt 
19259da57d7bSbt 			/* Set the SW EEPROM semaphore bit to request access */
19269da57d7bSbt 			swsm |= IXGBE_SWSM_SWESMBI;
1927dc0cb1cdSDale Ghent 			IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
19289da57d7bSbt 
19299da57d7bSbt 			/*
19309da57d7bSbt 			 * If we set the bit successfully then we got the
19319da57d7bSbt 			 * semaphore.
19329da57d7bSbt 			 */
1933dc0cb1cdSDale Ghent 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
19349da57d7bSbt 			if (swsm & IXGBE_SWSM_SWESMBI)
19359da57d7bSbt 				break;
19369da57d7bSbt 
19379da57d7bSbt 			usec_delay(50);
19389da57d7bSbt 		}
19399da57d7bSbt 
19409da57d7bSbt 		/*
19419da57d7bSbt 		 * Release semaphores and return error if SW EEPROM semaphore
19429da57d7bSbt 		 * was not granted because we don't have access to the EEPROM
19439da57d7bSbt 		 */
19449da57d7bSbt 		if (i >= timeout) {
1945dc0cb1cdSDale Ghent 			ERROR_REPORT1(IXGBE_ERROR_POLLING,
1946dc0cb1cdSDale Ghent 			    "SWESMBI Software EEPROM semaphore not granted.\n");
19479da57d7bSbt 			ixgbe_release_eeprom_semaphore(hw);
19489da57d7bSbt 			status = IXGBE_ERR_EEPROM;
19499da57d7bSbt 		}
195073cd555cSBin Tu - Sun Microsystems - Beijing China 	} else {
1951dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_POLLING,
1952dc0cb1cdSDale Ghent 			     "Software semaphore SMBI between device drivers "
1953dc0cb1cdSDale Ghent 			     "not granted.\n");
19549da57d7bSbt 	}
19559da57d7bSbt 
195663b3bba8SJerry Jelinek 	return status;
19579da57d7bSbt }
19589da57d7bSbt 
195963b3bba8SJerry Jelinek /**
196063b3bba8SJerry Jelinek  *  ixgbe_release_eeprom_semaphore - Release hardware semaphore
196163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
19629da57d7bSbt  *
196363b3bba8SJerry Jelinek  *  This function clears hardware semaphore bits.
196463b3bba8SJerry Jelinek  **/
ixgbe_release_eeprom_semaphore(struct ixgbe_hw * hw)196563b3bba8SJerry Jelinek static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
19669da57d7bSbt {
19679da57d7bSbt 	u32 swsm;
19689da57d7bSbt 
19693cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_release_eeprom_semaphore");
19703cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
19719da57d7bSbt 	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
19729da57d7bSbt 
19739da57d7bSbt 	/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
19749da57d7bSbt 	swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI);
19759da57d7bSbt 	IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
19769da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
19779da57d7bSbt }
19789da57d7bSbt 
197963b3bba8SJerry Jelinek /**
198063b3bba8SJerry Jelinek  *  ixgbe_ready_eeprom - Polls for EEPROM ready
198163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
198263b3bba8SJerry Jelinek  **/
ixgbe_ready_eeprom(struct ixgbe_hw * hw)198363b3bba8SJerry Jelinek static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
19849da57d7bSbt {
19859da57d7bSbt 	s32 status = IXGBE_SUCCESS;
19869da57d7bSbt 	u16 i;
19879da57d7bSbt 	u8 spi_stat_reg;
19889da57d7bSbt 
19893cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_ready_eeprom");
19903cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
19919da57d7bSbt 	/*
19929da57d7bSbt 	 * Read "Status Register" repeatedly until the LSB is cleared.  The
19939da57d7bSbt 	 * EEPROM will signal that the command has been completed by clearing
19949da57d7bSbt 	 * bit 0 of the internal status register.  If it's not cleared within
19959da57d7bSbt 	 * 5 milliseconds, then error out.
19969da57d7bSbt 	 */
19979da57d7bSbt 	for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) {
19989da57d7bSbt 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI,
199969b5a878SDan McDonald 					    IXGBE_EEPROM_OPCODE_BITS);
20009da57d7bSbt 		spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8);
20019da57d7bSbt 		if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI))
20029da57d7bSbt 			break;
20039da57d7bSbt 
20049da57d7bSbt 		usec_delay(5);
20059da57d7bSbt 		ixgbe_standby_eeprom(hw);
2006dc0cb1cdSDale Ghent 	}
20079da57d7bSbt 
20089da57d7bSbt 	/*
20099da57d7bSbt 	 * On some parts, SPI write time could vary from 0-20mSec on 3.3V
20109da57d7bSbt 	 * devices (and only 0-5mSec on 5V devices)
20119da57d7bSbt 	 */
20129da57d7bSbt 	if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
20139da57d7bSbt 		DEBUGOUT("SPI EEPROM Status error\n");
20149da57d7bSbt 		status = IXGBE_ERR_EEPROM;
20159da57d7bSbt 	}
20169da57d7bSbt 
201763b3bba8SJerry Jelinek 	return status;
20189da57d7bSbt }
20199da57d7bSbt 
202063b3bba8SJerry Jelinek /**
202163b3bba8SJerry Jelinek  *  ixgbe_standby_eeprom - Returns EEPROM to a "standby" state
202263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
202363b3bba8SJerry Jelinek  **/
ixgbe_standby_eeprom(struct ixgbe_hw * hw)202463b3bba8SJerry Jelinek static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
20259da57d7bSbt {
20269da57d7bSbt 	u32 eec;
20279da57d7bSbt 
20283cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_standby_eeprom");
20293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
2030dc0cb1cdSDale Ghent 	eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
20319da57d7bSbt 
20329da57d7bSbt 	/* Toggle CS to flush commands */
20339da57d7bSbt 	eec |= IXGBE_EEC_CS;
2034dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
20359da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
20369da57d7bSbt 	usec_delay(1);
20379da57d7bSbt 	eec &= ~IXGBE_EEC_CS;
2038dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
20399da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
20409da57d7bSbt 	usec_delay(1);
20419da57d7bSbt }
20429da57d7bSbt 
204363b3bba8SJerry Jelinek /**
204463b3bba8SJerry Jelinek  *  ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM.
204563b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
204663b3bba8SJerry Jelinek  *  @data: data to send to the EEPROM
204763b3bba8SJerry Jelinek  *  @count: number of bits to shift out
204863b3bba8SJerry Jelinek  **/
ixgbe_shift_out_eeprom_bits(struct ixgbe_hw * hw,u16 data,u16 count)204963b3bba8SJerry Jelinek static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
205069b5a878SDan McDonald 					u16 count)
20519da57d7bSbt {
20529da57d7bSbt 	u32 eec;
20539da57d7bSbt 	u32 mask;
20549da57d7bSbt 	u32 i;
20559da57d7bSbt 
20563cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_shift_out_eeprom_bits");
20573cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
2058dc0cb1cdSDale Ghent 	eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
20599da57d7bSbt 
20609da57d7bSbt 	/*
20619da57d7bSbt 	 * Mask is used to shift "count" bits of "data" out to the EEPROM
20629da57d7bSbt 	 * one bit at a time.  Determine the starting bit based on count
20639da57d7bSbt 	 */
20649da57d7bSbt 	mask = 0x01 << (count - 1);
20659da57d7bSbt 
20669da57d7bSbt 	for (i = 0; i < count; i++) {
20679da57d7bSbt 		/*
20689da57d7bSbt 		 * A "1" is shifted out to the EEPROM by setting bit "DI" to a
20699da57d7bSbt 		 * "1", and then raising and then lowering the clock (the SK
20709da57d7bSbt 		 * bit controls the clock input to the EEPROM).  A "0" is
20719da57d7bSbt 		 * shifted out to the EEPROM by setting "DI" to "0" and then
20729da57d7bSbt 		 * raising and then lowering the clock.
20739da57d7bSbt 		 */
20749da57d7bSbt 		if (data & mask)
20759da57d7bSbt 			eec |= IXGBE_EEC_DI;
20769da57d7bSbt 		else
20779da57d7bSbt 			eec &= ~IXGBE_EEC_DI;
20789da57d7bSbt 
2079dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
20809da57d7bSbt 		IXGBE_WRITE_FLUSH(hw);
20819da57d7bSbt 
20829da57d7bSbt 		usec_delay(1);
20839da57d7bSbt 
20849da57d7bSbt 		ixgbe_raise_eeprom_clk(hw, &eec);
20859da57d7bSbt 		ixgbe_lower_eeprom_clk(hw, &eec);
20869da57d7bSbt 
20879da57d7bSbt 		/*
20889da57d7bSbt 		 * Shift mask to signify next bit of data to shift in to the
20899da57d7bSbt 		 * EEPROM
20909da57d7bSbt 		 */
20919da57d7bSbt 		mask = mask >> 1;
2092dc0cb1cdSDale Ghent 	}
20939da57d7bSbt 
20949da57d7bSbt 	/* We leave the "DI" bit set to "0" when we leave this routine. */
20959da57d7bSbt 	eec &= ~IXGBE_EEC_DI;
2096dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
20979da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
20989da57d7bSbt }
20999da57d7bSbt 
210063b3bba8SJerry Jelinek /**
210163b3bba8SJerry Jelinek  *  ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
210263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
2103*48ed61a7SRobert Mustacchi  *  @count: number of bits to shift
210463b3bba8SJerry Jelinek  **/
ixgbe_shift_in_eeprom_bits(struct ixgbe_hw * hw,u16 count)210563b3bba8SJerry Jelinek static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
21069da57d7bSbt {
21079da57d7bSbt 	u32 eec;
21089da57d7bSbt 	u32 i;
21099da57d7bSbt 	u16 data = 0;
21109da57d7bSbt 
21113cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_shift_in_eeprom_bits");
21123cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
21139da57d7bSbt 	/*
21149da57d7bSbt 	 * In order to read a register from the EEPROM, we need to shift
21159da57d7bSbt 	 * 'count' bits in from the EEPROM. Bits are "shifted in" by raising
21169da57d7bSbt 	 * the clock input to the EEPROM (setting the SK bit), and then reading
21179da57d7bSbt 	 * the value of the "DO" bit.  During this "shifting in" process the
21189da57d7bSbt 	 * "DI" bit should always be clear.
21199da57d7bSbt 	 */
2120dc0cb1cdSDale Ghent 	eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
21219da57d7bSbt 
21229da57d7bSbt 	eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
21239da57d7bSbt 
21249da57d7bSbt 	for (i = 0; i < count; i++) {
21259da57d7bSbt 		data = data << 1;
21269da57d7bSbt 		ixgbe_raise_eeprom_clk(hw, &eec);
21279da57d7bSbt 
2128dc0cb1cdSDale Ghent 		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
21299da57d7bSbt 
21309da57d7bSbt 		eec &= ~(IXGBE_EEC_DI);
21319da57d7bSbt 		if (eec & IXGBE_EEC_DO)
21329da57d7bSbt 			data |= 1;
21339da57d7bSbt 
21349da57d7bSbt 		ixgbe_lower_eeprom_clk(hw, &eec);
21359da57d7bSbt 	}
21369da57d7bSbt 
213763b3bba8SJerry Jelinek 	return data;
21389da57d7bSbt }
21399da57d7bSbt 
214063b3bba8SJerry Jelinek /**
214163b3bba8SJerry Jelinek  *  ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input.
214263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
214363b3bba8SJerry Jelinek  *  @eec: EEC register's current value
214463b3bba8SJerry Jelinek  **/
ixgbe_raise_eeprom_clk(struct ixgbe_hw * hw,u32 * eec)214563b3bba8SJerry Jelinek static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
21469da57d7bSbt {
21473cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_raise_eeprom_clk");
21483cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
21499da57d7bSbt 	/*
21509da57d7bSbt 	 * Raise the clock input to the EEPROM
21519da57d7bSbt 	 * (setting the SK bit), then delay
21529da57d7bSbt 	 */
21539da57d7bSbt 	*eec = *eec | IXGBE_EEC_SK;
2154dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec);
21559da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
21569da57d7bSbt 	usec_delay(1);
21579da57d7bSbt }
21589da57d7bSbt 
215963b3bba8SJerry Jelinek /**
216063b3bba8SJerry Jelinek  *  ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input.
216163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
2162*48ed61a7SRobert Mustacchi  *  @eec: EEC's current value
216363b3bba8SJerry Jelinek  **/
ixgbe_lower_eeprom_clk(struct ixgbe_hw * hw,u32 * eec)216463b3bba8SJerry Jelinek static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
21659da57d7bSbt {
21663cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_lower_eeprom_clk");
21673cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
21689da57d7bSbt 	/*
21699da57d7bSbt 	 * Lower the clock input to the EEPROM (clearing the SK bit), then
21709da57d7bSbt 	 * delay
21719da57d7bSbt 	 */
21729da57d7bSbt 	*eec = *eec & ~IXGBE_EEC_SK;
2173dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec);
21749da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
21759da57d7bSbt 	usec_delay(1);
21769da57d7bSbt }
21779da57d7bSbt 
217863b3bba8SJerry Jelinek /**
217963b3bba8SJerry Jelinek  *  ixgbe_release_eeprom - Release EEPROM, release semaphores
218063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
218163b3bba8SJerry Jelinek  **/
ixgbe_release_eeprom(struct ixgbe_hw * hw)218263b3bba8SJerry Jelinek static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
21839da57d7bSbt {
21849da57d7bSbt 	u32 eec;
21859da57d7bSbt 
21863cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_release_eeprom");
21873cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
2188dc0cb1cdSDale Ghent 	eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
21899da57d7bSbt 
21909da57d7bSbt 	eec |= IXGBE_EEC_CS;  /* Pull CS high */
21919da57d7bSbt 	eec &= ~IXGBE_EEC_SK; /* Lower SCK */
21929da57d7bSbt 
2193dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
21949da57d7bSbt 	IXGBE_WRITE_FLUSH(hw);
21959da57d7bSbt 
21969da57d7bSbt 	usec_delay(1);
21979da57d7bSbt 
21989da57d7bSbt 	/* Stop requesting EEPROM access */
21999da57d7bSbt 	eec &= ~IXGBE_EEC_REQ;
2200dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
22019da57d7bSbt 
220269b5a878SDan McDonald 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
2203185c5677SPaul Guo 
2204185c5677SPaul Guo 	/* Delay before attempt to obtain semaphore again to allow FW access */
2205185c5677SPaul Guo 	msec_delay(hw->eeprom.semaphore_delay);
22069da57d7bSbt }
22079da57d7bSbt 
220863b3bba8SJerry Jelinek /**
220963b3bba8SJerry Jelinek  *  ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
221063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
2211dc0cb1cdSDale Ghent  *
2212dc0cb1cdSDale Ghent  *  Returns a negative error code on error, or the 16-bit checksum
221363b3bba8SJerry Jelinek  **/
ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw * hw)2214dc0cb1cdSDale Ghent s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
22159da57d7bSbt {
22169da57d7bSbt 	u16 i;
22179da57d7bSbt 	u16 j;
22189da57d7bSbt 	u16 checksum = 0;
22199da57d7bSbt 	u16 length = 0;
22209da57d7bSbt 	u16 pointer = 0;
22219da57d7bSbt 	u16 word = 0;
22229da57d7bSbt 
222319843f01SPaul Guo 	DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic");
22243cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
22259da57d7bSbt 	/* Include 0x0-0x3F in the checksum */
22269da57d7bSbt 	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
2227dc0cb1cdSDale Ghent 		if (hw->eeprom.ops.read(hw, i, &word)) {
22289da57d7bSbt 			DEBUGOUT("EEPROM read failed\n");
2229dc0cb1cdSDale Ghent 			return IXGBE_ERR_EEPROM;
22309da57d7bSbt 		}
22319da57d7bSbt 		checksum += word;
22329da57d7bSbt 	}
22339da57d7bSbt 
22349da57d7bSbt 	/* Include all data from pointers except for the fw pointer */
22359da57d7bSbt 	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
2236dc0cb1cdSDale Ghent 		if (hw->eeprom.ops.read(hw, i, &pointer)) {
2237dc0cb1cdSDale Ghent 			DEBUGOUT("EEPROM read failed\n");
2238dc0cb1cdSDale Ghent 			return IXGBE_ERR_EEPROM;
2239dc0cb1cdSDale Ghent 		}
2240dc0cb1cdSDale Ghent 
2241dc0cb1cdSDale Ghent 		/* If the pointer seems invalid */
2242dc0cb1cdSDale Ghent 		if (pointer == 0xFFFF || pointer == 0)
2243dc0cb1cdSDale Ghent 			continue;
2244dc0cb1cdSDale Ghent 
2245dc0cb1cdSDale Ghent 		if (hw->eeprom.ops.read(hw, pointer, &length)) {
2246dc0cb1cdSDale Ghent 			DEBUGOUT("EEPROM read failed\n");
2247dc0cb1cdSDale Ghent 			return IXGBE_ERR_EEPROM;
2248dc0cb1cdSDale Ghent 		}
22499da57d7bSbt 
2250dc0cb1cdSDale Ghent 		if (length == 0xFFFF || length == 0)
2251dc0cb1cdSDale Ghent 			continue;
22529da57d7bSbt 
2253dc0cb1cdSDale Ghent 		for (j = pointer + 1; j <= pointer + length; j++) {
2254dc0cb1cdSDale Ghent 			if (hw->eeprom.ops.read(hw, j, &word)) {
2255dc0cb1cdSDale Ghent 				DEBUGOUT("EEPROM read failed\n");
2256dc0cb1cdSDale Ghent 				return IXGBE_ERR_EEPROM;
22579da57d7bSbt 			}
2258dc0cb1cdSDale Ghent 			checksum += word;
22599da57d7bSbt 		}
22609da57d7bSbt 	}
22619da57d7bSbt 
22629da57d7bSbt 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
22639da57d7bSbt 
2264dc0cb1cdSDale Ghent 	return (s32)checksum;
22659da57d7bSbt }
22669da57d7bSbt 
226763b3bba8SJerry Jelinek /**
226863b3bba8SJerry Jelinek  *  ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
226963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
227063b3bba8SJerry Jelinek  *  @checksum_val: calculated checksum
22719da57d7bSbt  *
227263b3bba8SJerry Jelinek  *  Performs checksum calculation and validates the EEPROM checksum.  If the
227363b3bba8SJerry Jelinek  *  caller does not need checksum_val, the value can be NULL.
227463b3bba8SJerry Jelinek  **/
ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw * hw,u16 * checksum_val)227563b3bba8SJerry Jelinek s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
227669b5a878SDan McDonald 					   u16 *checksum_val)
22779da57d7bSbt {
22789da57d7bSbt 	s32 status;
22799da57d7bSbt 	u16 checksum;
22809da57d7bSbt 	u16 read_checksum = 0;
22819da57d7bSbt 
22823cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic");
22833cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
2284dc0cb1cdSDale Ghent 	/* Read the first word from the EEPROM. If this times out or fails, do
22859da57d7bSbt 	 * not continue or we could be in for a very long wait while every
22869da57d7bSbt 	 * EEPROM read fails
22879da57d7bSbt 	 */
22889da57d7bSbt 	status = hw->eeprom.ops.read(hw, 0, &checksum);
2289dc0cb1cdSDale Ghent 	if (status) {
2290dc0cb1cdSDale Ghent 		DEBUGOUT("EEPROM read failed\n");
2291dc0cb1cdSDale Ghent 		return status;
2292dc0cb1cdSDale Ghent 	}
22939da57d7bSbt 
2294dc0cb1cdSDale Ghent 	status = hw->eeprom.ops.calc_checksum(hw);
2295dc0cb1cdSDale Ghent 	if (status < 0)
2296dc0cb1cdSDale Ghent 		return status;
22979da57d7bSbt 
2298dc0cb1cdSDale Ghent 	checksum = (u16)(status & 0xffff);
22999da57d7bSbt 
2300dc0cb1cdSDale Ghent 	status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
2301dc0cb1cdSDale Ghent 	if (status) {
23029da57d7bSbt 		DEBUGOUT("EEPROM read failed\n");
2303dc0cb1cdSDale Ghent 		return status;
23049da57d7bSbt 	}
23059da57d7bSbt 
2306dc0cb1cdSDale Ghent 	/* Verify read checksum from EEPROM is the same as
2307dc0cb1cdSDale Ghent 	 * calculated checksum
2308dc0cb1cdSDale Ghent 	 */
2309dc0cb1cdSDale Ghent 	if (read_checksum != checksum)
2310dc0cb1cdSDale Ghent 		status = IXGBE_ERR_EEPROM_CHECKSUM;
2311dc0cb1cdSDale Ghent 
2312dc0cb1cdSDale Ghent 	/* If the user cares, return the calculated checksum */
2313dc0cb1cdSDale Ghent 	if (checksum_val)
2314dc0cb1cdSDale Ghent 		*checksum_val = checksum;
2315dc0cb1cdSDale Ghent 
231663b3bba8SJerry Jelinek 	return status;
23179da57d7bSbt }
23189da57d7bSbt 
231963b3bba8SJerry Jelinek /**
232063b3bba8SJerry Jelinek  *  ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum
232163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
232263b3bba8SJerry Jelinek  **/
ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw * hw)232363b3bba8SJerry Jelinek s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
23249da57d7bSbt {
23259da57d7bSbt 	s32 status;
23269da57d7bSbt 	u16 checksum;
23279da57d7bSbt 
23283cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_update_eeprom_checksum_generic");
23293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
2330dc0cb1cdSDale Ghent 	/* Read the first word from the EEPROM. If this times out or fails, do
23319da57d7bSbt 	 * not continue or we could be in for a very long wait while every
23329da57d7bSbt 	 * EEPROM read fails
23339da57d7bSbt 	 */
23349da57d7bSbt 	status = hw->eeprom.ops.read(hw, 0, &checksum);
2335dc0cb1cdSDale Ghent 	if (status) {
23369da57d7bSbt 		DEBUGOUT("EEPROM read failed\n");
2337dc0cb1cdSDale Ghent 		return status;
23389da57d7bSbt 	}
23399da57d7bSbt 
2340dc0cb1cdSDale Ghent 	status = hw->eeprom.ops.calc_checksum(hw);
2341dc0cb1cdSDale Ghent 	if (status < 0)
2342dc0cb1cdSDale Ghent 		return status;
2343dc0cb1cdSDale Ghent 
2344dc0cb1cdSDale Ghent 	checksum = (u16)(status & 0xffff);
2345dc0cb1cdSDale Ghent 
2346dc0cb1cdSDale Ghent 	status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum);
2347dc0cb1cdSDale Ghent 
234863b3bba8SJerry Jelinek 	return status;
23499da57d7bSbt }
23509da57d7bSbt 
235163b3bba8SJerry Jelinek /**
235263b3bba8SJerry Jelinek  *  ixgbe_validate_mac_addr - Validate MAC address
235363b3bba8SJerry Jelinek  *  @mac_addr: pointer to MAC address.
23549da57d7bSbt  *
2355*48ed61a7SRobert Mustacchi  *  Tests a MAC address to ensure it is a valid Individual Address.
235663b3bba8SJerry Jelinek  **/
ixgbe_validate_mac_addr(u8 * mac_addr)235763b3bba8SJerry Jelinek s32 ixgbe_validate_mac_addr(u8 *mac_addr)
23589da57d7bSbt {
23599da57d7bSbt 	s32 status = IXGBE_SUCCESS;
23609da57d7bSbt 
23613cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_validate_mac_addr");
23623cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
23639da57d7bSbt 	/* Make sure it is not a multicast address */
23649da57d7bSbt 	if (IXGBE_IS_MULTICAST(mac_addr)) {
23659da57d7bSbt 		status = IXGBE_ERR_INVALID_MAC_ADDR;
23669da57d7bSbt 	/* Not a broadcast address */
23679da57d7bSbt 	} else if (IXGBE_IS_BROADCAST(mac_addr)) {
23689da57d7bSbt 		status = IXGBE_ERR_INVALID_MAC_ADDR;
23699da57d7bSbt 	/* Reject the zero address */
23709da57d7bSbt 	} else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
237169b5a878SDan McDonald 		   mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
23729da57d7bSbt 		status = IXGBE_ERR_INVALID_MAC_ADDR;
23739da57d7bSbt 	}
237463b3bba8SJerry Jelinek 	return status;
23759da57d7bSbt }
23769da57d7bSbt 
237763b3bba8SJerry Jelinek /**
237863b3bba8SJerry Jelinek  *  ixgbe_set_rar_generic - Set Rx address register
237963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
238063b3bba8SJerry Jelinek  *  @index: Receive address register to write
238163b3bba8SJerry Jelinek  *  @addr: Address to put into receive address register
238263b3bba8SJerry Jelinek  *  @vmdq: VMDq "set" or "pool" index
238363b3bba8SJerry Jelinek  *  @enable_addr: set flag that address is active
23849da57d7bSbt  *
238563b3bba8SJerry Jelinek  *  Puts an ethernet address into a receive address register.
238663b3bba8SJerry Jelinek  **/
ixgbe_set_rar_generic(struct ixgbe_hw * hw,u32 index,u8 * addr,u32 vmdq,u32 enable_addr)238763b3bba8SJerry Jelinek s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
238869b5a878SDan McDonald 			  u32 enable_addr)
23899da57d7bSbt {
23909da57d7bSbt 	u32 rar_low, rar_high;
23919da57d7bSbt 	u32 rar_entries = hw->mac.num_rar_entries;
23929da57d7bSbt 
23933cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_set_rar_generic");
23943cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
239563b3bba8SJerry Jelinek 	/* Make sure we are using a valid rar index range */
239663b3bba8SJerry Jelinek 	if (index >= rar_entries) {
2397dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_ARGUMENT,
2398dc0cb1cdSDale Ghent 			     "RAR index %d is out of range.\n", index);
239963b3bba8SJerry Jelinek 		return IXGBE_ERR_INVALID_ARGUMENT;
240063b3bba8SJerry Jelinek 	}
240163b3bba8SJerry Jelinek 
24029da57d7bSbt 	/* setup VMDq pool selection before this RAR gets enabled */
24039da57d7bSbt 	hw->mac.ops.set_vmdq(hw, index, vmdq);
24049da57d7bSbt 
240563b3bba8SJerry Jelinek 	/*
240663b3bba8SJerry Jelinek 	 * HW expects these in little endian so we reverse the byte
240763b3bba8SJerry Jelinek 	 * order from network order (big endian) to little endian
240863b3bba8SJerry Jelinek 	 */
240963b3bba8SJerry Jelinek 	rar_low = ((u32)addr[0] |
241069b5a878SDan McDonald 		   ((u32)addr[1] << 8) |
241169b5a878SDan McDonald 		   ((u32)addr[2] << 16) |
241269b5a878SDan McDonald 		   ((u32)addr[3] << 24));
241363b3bba8SJerry Jelinek 	/*
241463b3bba8SJerry Jelinek 	 * Some parts put the VMDq setting in the extra RAH bits,
241563b3bba8SJerry Jelinek 	 * so save everything except the lower 16 bits that hold part
241663b3bba8SJerry Jelinek 	 * of the address and the address valid bit.
241763b3bba8SJerry Jelinek 	 */
241863b3bba8SJerry Jelinek 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
241963b3bba8SJerry Jelinek 	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
242063b3bba8SJerry Jelinek 	rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
24219da57d7bSbt 
242263b3bba8SJerry Jelinek 	if (enable_addr != 0)
242363b3bba8SJerry Jelinek 		rar_high |= IXGBE_RAH_AV;
24249da57d7bSbt 
242563b3bba8SJerry Jelinek 	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
242663b3bba8SJerry Jelinek 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
242713740cb2SPaul Guo 
242863b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
242913740cb2SPaul Guo }
243013740cb2SPaul Guo 
243163b3bba8SJerry Jelinek /**
243263b3bba8SJerry Jelinek  *  ixgbe_clear_rar_generic - Remove Rx address register
243363b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
243463b3bba8SJerry Jelinek  *  @index: Receive address register to write
243513740cb2SPaul Guo  *
243663b3bba8SJerry Jelinek  *  Clears an ethernet address from a receive address register.
243763b3bba8SJerry Jelinek  **/
ixgbe_clear_rar_generic(struct ixgbe_hw * hw,u32 index)243863b3bba8SJerry Jelinek s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
243913740cb2SPaul Guo {
244013740cb2SPaul Guo 	u32 rar_high;
244113740cb2SPaul Guo 	u32 rar_entries = hw->mac.num_rar_entries;
244213740cb2SPaul Guo 
24433cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_clear_rar_generic");
24443cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
244513740cb2SPaul Guo 	/* Make sure we are using a valid rar index range */
244663b3bba8SJerry Jelinek 	if (index >= rar_entries) {
2447dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_ARGUMENT,
2448dc0cb1cdSDale Ghent 			     "RAR index %d is out of range.\n", index);
244963b3bba8SJerry Jelinek 		return IXGBE_ERR_INVALID_ARGUMENT;
24509da57d7bSbt 	}
24519da57d7bSbt 
245263b3bba8SJerry Jelinek 	/*
245363b3bba8SJerry Jelinek 	 * Some parts put the VMDq setting in the extra RAH bits,
245463b3bba8SJerry Jelinek 	 * so save everything except the lower 16 bits that hold part
245563b3bba8SJerry Jelinek 	 * of the address and the address valid bit.
245663b3bba8SJerry Jelinek 	 */
245763b3bba8SJerry Jelinek 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
245863b3bba8SJerry Jelinek 	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
245963b3bba8SJerry Jelinek 
246063b3bba8SJerry Jelinek 	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
246163b3bba8SJerry Jelinek 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
246263b3bba8SJerry Jelinek 
246313740cb2SPaul Guo 	/* clear VMDq pool/queue selection for this RAR */
246413740cb2SPaul Guo 	hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
246513740cb2SPaul Guo 
246663b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
24679da57d7bSbt }
24689da57d7bSbt 
246963b3bba8SJerry Jelinek /**
247063b3bba8SJerry Jelinek  *  ixgbe_init_rx_addrs_generic - Initializes receive address filters.
247163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
24729da57d7bSbt  *
247363b3bba8SJerry Jelinek  *  Places the MAC address in receive address register 0 and clears the rest
247463b3bba8SJerry Jelinek  *  of the receive address registers. Clears the multicast table. Assumes
247563b3bba8SJerry Jelinek  *  the receiver is in reset when the routine is called.
247663b3bba8SJerry Jelinek  **/
ixgbe_init_rx_addrs_generic(struct ixgbe_hw * hw)247763b3bba8SJerry Jelinek s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
24789da57d7bSbt {
24799da57d7bSbt 	u32 i;
24809da57d7bSbt 	u32 rar_entries = hw->mac.num_rar_entries;
24819da57d7bSbt 
24823cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_init_rx_addrs_generic");
24833cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
24849da57d7bSbt 	/*
24859da57d7bSbt 	 * If the current mac address is valid, assume it is a software override
24869da57d7bSbt 	 * to the permanent address.
24879da57d7bSbt 	 * Otherwise, use the permanent address from the eeprom.
24889da57d7bSbt 	 */
24899da57d7bSbt 	if (ixgbe_validate_mac_addr(hw->mac.addr) ==
24909da57d7bSbt 	    IXGBE_ERR_INVALID_MAC_ADDR) {
24919da57d7bSbt 		/* Get the MAC address from the RAR0 for later reference */
24929da57d7bSbt 		hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
24939da57d7bSbt 
24949da57d7bSbt 		DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
249569b5a878SDan McDonald 			  hw->mac.addr[0], hw->mac.addr[1],
249669b5a878SDan McDonald 			  hw->mac.addr[2]);
24979da57d7bSbt 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
249869b5a878SDan McDonald 			  hw->mac.addr[4], hw->mac.addr[5]);
24999da57d7bSbt 	} else {
25009da57d7bSbt 		/* Setup the receive address. */
25019da57d7bSbt 		DEBUGOUT("Overriding MAC Address in RAR[0]\n");
25029da57d7bSbt 		DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
250369b5a878SDan McDonald 			  hw->mac.addr[0], hw->mac.addr[1],
250469b5a878SDan McDonald 			  hw->mac.addr[2]);
25059da57d7bSbt 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
250669b5a878SDan McDonald 			  hw->mac.addr[4], hw->mac.addr[5]);
25079da57d7bSbt 
25089da57d7bSbt 		hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
25099da57d7bSbt 	}
2510*48ed61a7SRobert Mustacchi 
2511*48ed61a7SRobert Mustacchi 	/* clear VMDq pool/queue selection for RAR 0 */
2512*48ed61a7SRobert Mustacchi 	hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL);
2513*48ed61a7SRobert Mustacchi 
25149da57d7bSbt 	hw->addr_ctrl.overflow_promisc = 0;
25159da57d7bSbt 
25169da57d7bSbt 	hw->addr_ctrl.rar_used_count = 1;
25179da57d7bSbt 
25189da57d7bSbt 	/* Zero out the other receive addresses. */
25199da57d7bSbt 	DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1);
25209da57d7bSbt 	for (i = 1; i < rar_entries; i++) {
25219da57d7bSbt 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
25229da57d7bSbt 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
25239da57d7bSbt 	}
25249da57d7bSbt 
25259da57d7bSbt 	/* Clear the MTA */
25269da57d7bSbt 	hw->addr_ctrl.mta_in_use = 0;
25279da57d7bSbt 	IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
25289da57d7bSbt 
25299da57d7bSbt 	DEBUGOUT(" Clearing MTA\n");
25309da57d7bSbt 	for (i = 0; i < hw->mac.mcft_size; i++)
25319da57d7bSbt 		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
25329da57d7bSbt 
2533dc0cb1cdSDale Ghent 	ixgbe_init_uta_tables(hw);
2534dc0cb1cdSDale Ghent 
2535dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
25369da57d7bSbt }
25379da57d7bSbt 
253863b3bba8SJerry Jelinek /**
253963b3bba8SJerry Jelinek  *  ixgbe_add_uc_addr - Adds a secondary unicast address.
254063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
254163b3bba8SJerry Jelinek  *  @addr: new address
2542*48ed61a7SRobert Mustacchi  *  @vmdq: VMDq "set" or "pool" index
25439da57d7bSbt  *
254463b3bba8SJerry Jelinek  *  Adds it to unused receive address register or goes into promiscuous mode.
254563b3bba8SJerry Jelinek  **/
ixgbe_add_uc_addr(struct ixgbe_hw * hw,u8 * addr,u32 vmdq)254663b3bba8SJerry Jelinek void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
25479da57d7bSbt {
25489da57d7bSbt 	u32 rar_entries = hw->mac.num_rar_entries;
25499da57d7bSbt 	u32 rar;
25509da57d7bSbt 
25513cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_add_uc_addr");
25523cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
25539da57d7bSbt 	DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
255469b5a878SDan McDonald 		  addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
25559da57d7bSbt 
25569da57d7bSbt 	/*
25579da57d7bSbt 	 * Place this address in the RAR if there is room,
25589da57d7bSbt 	 * else put the controller into promiscuous mode
25599da57d7bSbt 	 */
25609da57d7bSbt 	if (hw->addr_ctrl.rar_used_count < rar_entries) {
256173cd555cSBin Tu - Sun Microsystems - Beijing China 		rar = hw->addr_ctrl.rar_used_count;
25629da57d7bSbt 		hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
25639da57d7bSbt 		DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar);
25649da57d7bSbt 		hw->addr_ctrl.rar_used_count++;
25659da57d7bSbt 	} else {
25669da57d7bSbt 		hw->addr_ctrl.overflow_promisc++;
25679da57d7bSbt 	}
25689da57d7bSbt 
25699da57d7bSbt 	DEBUGOUT("ixgbe_add_uc_addr Complete\n");
25709da57d7bSbt }
25719da57d7bSbt 
257263b3bba8SJerry Jelinek /**
257363b3bba8SJerry Jelinek  *  ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
257463b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
257563b3bba8SJerry Jelinek  *  @addr_list: the list of new addresses
257663b3bba8SJerry Jelinek  *  @addr_count: number of addresses
257763b3bba8SJerry Jelinek  *  @next: iterator function to walk the address list
25789da57d7bSbt  *
257963b3bba8SJerry Jelinek  *  The given list replaces any existing list.  Clears the secondary addrs from
258063b3bba8SJerry Jelinek  *  receive address registers.  Uses unused receive address registers for the
258163b3bba8SJerry Jelinek  *  first secondary addresses, and falls back to promiscuous mode as needed.
25829da57d7bSbt  *
258363b3bba8SJerry Jelinek  *  Drivers using secondary unicast addresses must set user_set_promisc when
258463b3bba8SJerry Jelinek  *  manually putting the device into promiscuous mode.
258563b3bba8SJerry Jelinek  **/
ixgbe_update_uc_addr_list_generic(struct ixgbe_hw * hw,u8 * addr_list,u32 addr_count,ixgbe_mc_addr_itr next)258663b3bba8SJerry Jelinek s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
258769b5a878SDan McDonald 				      u32 addr_count, ixgbe_mc_addr_itr next)
25889da57d7bSbt {
25899da57d7bSbt 	u8 *addr;
25909da57d7bSbt 	u32 i;
25919da57d7bSbt 	u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
25929da57d7bSbt 	u32 uc_addr_in_use;
25939da57d7bSbt 	u32 fctrl;
25949da57d7bSbt 	u32 vmdq;
25959da57d7bSbt 
25963cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_update_uc_addr_list_generic");
25973cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
25989da57d7bSbt 	/*
25999da57d7bSbt 	 * Clear accounting of old secondary address list,
26009da57d7bSbt 	 * don't count RAR[0]
26019da57d7bSbt 	 */
260273cd555cSBin Tu - Sun Microsystems - Beijing China 	uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1;
26039da57d7bSbt 	hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
26049da57d7bSbt 	hw->addr_ctrl.overflow_promisc = 0;
26059da57d7bSbt 
26069da57d7bSbt 	/* Zero out the other receive addresses */
260763b3bba8SJerry Jelinek 	DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1);
260819843f01SPaul Guo 	for (i = 0; i < uc_addr_in_use; i++) {
260963b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0);
261063b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0);
26119da57d7bSbt 	}
26129da57d7bSbt 
26139da57d7bSbt 	/* Add the new addresses */
26149da57d7bSbt 	for (i = 0; i < addr_count; i++) {
26159da57d7bSbt 		DEBUGOUT(" Adding the secondary addresses:\n");
26169da57d7bSbt 		addr = next(hw, &addr_list, &vmdq);
26179da57d7bSbt 		ixgbe_add_uc_addr(hw, addr, vmdq);
26189da57d7bSbt 	}
26199da57d7bSbt 
26209da57d7bSbt 	if (hw->addr_ctrl.overflow_promisc) {
26219da57d7bSbt 		/* enable promisc if not already in overflow or set by user */
26229da57d7bSbt 		if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
26239da57d7bSbt 			DEBUGOUT(" Entering address overflow promisc mode\n");
26249da57d7bSbt 			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
26259da57d7bSbt 			fctrl |= IXGBE_FCTRL_UPE;
26269da57d7bSbt 			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
26279da57d7bSbt 		}
26289da57d7bSbt 	} else {
26299da57d7bSbt 		/* only disable if set by overflow, not by user */
26309da57d7bSbt 		if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
26319da57d7bSbt 			DEBUGOUT(" Leaving address overflow promisc mode\n");
26329da57d7bSbt 			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
26339da57d7bSbt 			fctrl &= ~IXGBE_FCTRL_UPE;
26349da57d7bSbt 			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
26359da57d7bSbt 		}
26369da57d7bSbt 	}
26379da57d7bSbt 
26389da57d7bSbt 	DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n");
263963b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
26409da57d7bSbt }
26419da57d7bSbt 
264263b3bba8SJerry Jelinek /**
264363b3bba8SJerry Jelinek  *  ixgbe_mta_vector - Determines bit-vector in multicast table to set
264463b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
264563b3bba8SJerry Jelinek  *  @mc_addr: the multicast address
26469da57d7bSbt  *
264763b3bba8SJerry Jelinek  *  Extracts the 12 bits, from a multicast address, to determine which
264863b3bba8SJerry Jelinek  *  bit-vector to set in the multicast table. The hardware uses 12 bits, from
264963b3bba8SJerry Jelinek  *  incoming rx multicast addresses, to determine the bit-vector to check in
265063b3bba8SJerry Jelinek  *  the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
265163b3bba8SJerry Jelinek  *  by the MO field of the MCSTCTRL. The MO field is set during initialization
265263b3bba8SJerry Jelinek  *  to mc_filter_type.
265363b3bba8SJerry Jelinek  **/
ixgbe_mta_vector(struct ixgbe_hw * hw,u8 * mc_addr)265463b3bba8SJerry Jelinek static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
26559da57d7bSbt {
26569da57d7bSbt 	u32 vector = 0;
26579da57d7bSbt 
26583cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_mta_vector");
26593cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
26609da57d7bSbt 	switch (hw->mac.mc_filter_type) {
26619da57d7bSbt 	case 0:   /* use bits [47:36] of the address */
26629da57d7bSbt 		vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
26639da57d7bSbt 		break;
26649da57d7bSbt 	case 1:   /* use bits [46:35] of the address */
26659da57d7bSbt 		vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
26669da57d7bSbt 		break;
26679da57d7bSbt 	case 2:   /* use bits [45:34] of the address */
26689da57d7bSbt 		vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
26699da57d7bSbt 		break;
26709da57d7bSbt 	case 3:   /* use bits [43:32] of the address */
26719da57d7bSbt 		vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
26729da57d7bSbt 		break;
26739da57d7bSbt 	default:  /* Invalid mc_filter_type */
26749da57d7bSbt 		DEBUGOUT("MC filter type param set incorrectly\n");
26759da57d7bSbt 		ASSERT(0);
26769da57d7bSbt 		break;
26779da57d7bSbt 	}
26789da57d7bSbt 
26799da57d7bSbt 	/* vector can only be 12-bits or boundary will be exceeded */
26809da57d7bSbt 	vector &= 0xFFF;
268163b3bba8SJerry Jelinek 	return vector;
26829da57d7bSbt }
26839da57d7bSbt 
268463b3bba8SJerry Jelinek /**
268563b3bba8SJerry Jelinek  *  ixgbe_set_mta - Set bit-vector in multicast table
268663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
2687*48ed61a7SRobert Mustacchi  *  @mc_addr: Multicast address
26889da57d7bSbt  *
268963b3bba8SJerry Jelinek  *  Sets the bit-vector in the multicast table.
269063b3bba8SJerry Jelinek  **/
ixgbe_set_mta(struct ixgbe_hw * hw,u8 * mc_addr)269163b3bba8SJerry Jelinek void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
26929da57d7bSbt {
26939da57d7bSbt 	u32 vector;
26949da57d7bSbt 	u32 vector_bit;
26959da57d7bSbt 	u32 vector_reg;
26969da57d7bSbt 
26973cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_set_mta");
26983cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
26999da57d7bSbt 	hw->addr_ctrl.mta_in_use++;
27009da57d7bSbt 
27019da57d7bSbt 	vector = ixgbe_mta_vector(hw, mc_addr);
27029da57d7bSbt 	DEBUGOUT1(" bit-vector = 0x%03X\n", vector);
27039da57d7bSbt 
27049da57d7bSbt 	/*
27059da57d7bSbt 	 * The MTA is a register array of 128 32-bit registers. It is treated
27069da57d7bSbt 	 * like an array of 4096 bits.  We want to set bit
27079da57d7bSbt 	 * BitArray[vector_value]. So we figure out what register the bit is
27089da57d7bSbt 	 * in, read it, OR in the new bit, then write back the new value.  The
27099da57d7bSbt 	 * register is determined by the upper 7 bits of the vector value and
27109da57d7bSbt 	 * the bit within that register are determined by the lower 5 bits of
27119da57d7bSbt 	 * the value.
27129da57d7bSbt 	 */
27139da57d7bSbt 	vector_reg = (vector >> 5) & 0x7F;
27149da57d7bSbt 	vector_bit = vector & 0x1F;
27155b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit);
27169da57d7bSbt }
27179da57d7bSbt 
271863b3bba8SJerry Jelinek /**
271963b3bba8SJerry Jelinek  *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
272063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
272163b3bba8SJerry Jelinek  *  @mc_addr_list: the list of new multicast addresses
272263b3bba8SJerry Jelinek  *  @mc_addr_count: number of addresses
272363b3bba8SJerry Jelinek  *  @next: iterator function to walk the multicast address list
272469b5a878SDan McDonald  *  @clear: flag, when set clears the table beforehand
27259da57d7bSbt  *
272669b5a878SDan McDonald  *  When the clear flag is set, the given list replaces any existing list.
272769b5a878SDan McDonald  *  Hashes the given addresses into the multicast table.
272863b3bba8SJerry Jelinek  **/
ixgbe_update_mc_addr_list_generic(struct ixgbe_hw * hw,u8 * mc_addr_list,u32 mc_addr_count,ixgbe_mc_addr_itr next,bool clear)272963b3bba8SJerry Jelinek s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
273069b5a878SDan McDonald 				      u32 mc_addr_count, ixgbe_mc_addr_itr next,
273169b5a878SDan McDonald 				      bool clear)
27329da57d7bSbt {
27339da57d7bSbt 	u32 i;
27349da57d7bSbt 	u32 vmdq;
27359da57d7bSbt 
27363cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_update_mc_addr_list_generic");
27373cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
27389da57d7bSbt 	/*
27399da57d7bSbt 	 * Set the new number of MC addresses that we are being requested to
27409da57d7bSbt 	 * use.
27419da57d7bSbt 	 */
27429da57d7bSbt 	hw->addr_ctrl.num_mc_addrs = mc_addr_count;
27439da57d7bSbt 	hw->addr_ctrl.mta_in_use = 0;
27449da57d7bSbt 
27455b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/* Clear mta_shadow */
274669b5a878SDan McDonald 	if (clear) {
274769b5a878SDan McDonald 		DEBUGOUT(" Clearing MTA\n");
2748dc0cb1cdSDale Ghent 		memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
274969b5a878SDan McDonald 	}
27509da57d7bSbt 
27515b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/* Update mta_shadow */
27529da57d7bSbt 	for (i = 0; i < mc_addr_count; i++) {
27539da57d7bSbt 		DEBUGOUT(" Adding the multicast addresses:\n");
275473cd555cSBin Tu - Sun Microsystems - Beijing China 		ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq));
27559da57d7bSbt 	}
27569da57d7bSbt 
27579da57d7bSbt 	/* Enable mta */
27585b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	for (i = 0; i < hw->mac.mcft_size; i++)
27595b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i,
276063b3bba8SJerry Jelinek 				      hw->mac.mta_shadow[i]);
27615b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
27629da57d7bSbt 	if (hw->addr_ctrl.mta_in_use > 0)
27639da57d7bSbt 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
276469b5a878SDan McDonald 				IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
27659da57d7bSbt 
27669da57d7bSbt 	DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n");
276763b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
27689da57d7bSbt }
27699da57d7bSbt 
277063b3bba8SJerry Jelinek /**
277163b3bba8SJerry Jelinek  *  ixgbe_enable_mc_generic - Enable multicast address in RAR
277263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
27739da57d7bSbt  *
277463b3bba8SJerry Jelinek  *  Enables multicast address in RAR and the use of the multicast hash table.
277563b3bba8SJerry Jelinek  **/
ixgbe_enable_mc_generic(struct ixgbe_hw * hw)277663b3bba8SJerry Jelinek s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
27779da57d7bSbt {
27789da57d7bSbt 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
27799da57d7bSbt 
27803cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_enable_mc_generic");
27813cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
27829da57d7bSbt 	if (a->mta_in_use > 0)
27839da57d7bSbt 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
278469b5a878SDan McDonald 				hw->mac.mc_filter_type);
27859da57d7bSbt 
278663b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
27879da57d7bSbt }
27889da57d7bSbt 
278963b3bba8SJerry Jelinek /**
279063b3bba8SJerry Jelinek  *  ixgbe_disable_mc_generic - Disable multicast address in RAR
279163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
27929da57d7bSbt  *
279363b3bba8SJerry Jelinek  *  Disables multicast address in RAR and the use of the multicast hash table.
279463b3bba8SJerry Jelinek  **/
ixgbe_disable_mc_generic(struct ixgbe_hw * hw)279563b3bba8SJerry Jelinek s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
27969da57d7bSbt {
27979da57d7bSbt 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
27989da57d7bSbt 
27993cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_disable_mc_generic");
28003cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
28019da57d7bSbt 	if (a->mta_in_use > 0)
28029da57d7bSbt 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
28039da57d7bSbt 
280463b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
28059da57d7bSbt }
28069da57d7bSbt 
280763b3bba8SJerry Jelinek /**
280863b3bba8SJerry Jelinek  *  ixgbe_fc_enable_generic - Enable flow control
280963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
281073cd555cSBin Tu - Sun Microsystems - Beijing China  *
281163b3bba8SJerry Jelinek  *  Enable flow control according to the current settings.
281263b3bba8SJerry Jelinek  **/
ixgbe_fc_enable_generic(struct ixgbe_hw * hw)281369b5a878SDan McDonald s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
281473cd555cSBin Tu - Sun Microsystems - Beijing China {
281573cd555cSBin Tu - Sun Microsystems - Beijing China 	s32 ret_val = IXGBE_SUCCESS;
281673cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 mflcn_reg, fccfg_reg;
281773cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 reg;
281863b3bba8SJerry Jelinek 	u32 fcrtl, fcrth;
281969b5a878SDan McDonald 	int i;
282073cd555cSBin Tu - Sun Microsystems - Beijing China 
282173cd555cSBin Tu - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_fc_enable_generic");
282273cd555cSBin Tu - Sun Microsystems - Beijing China 
282369b5a878SDan McDonald 	/* Validate the water mark configuration */
282469b5a878SDan McDonald 	if (!hw->fc.pause_time) {
282569b5a878SDan McDonald 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
282673cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
282769b5a878SDan McDonald 	}
282869b5a878SDan McDonald 
282969b5a878SDan McDonald 	/* Low water mark of zero causes XOFF floods */
283069b5a878SDan McDonald 	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
283169b5a878SDan McDonald 		if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
283269b5a878SDan McDonald 		    hw->fc.high_water[i]) {
283369b5a878SDan McDonald 			if (!hw->fc.low_water[i] ||
283469b5a878SDan McDonald 			    hw->fc.low_water[i] >= hw->fc.high_water[i]) {
283569b5a878SDan McDonald 				DEBUGOUT("Invalid water mark configuration\n");
283669b5a878SDan McDonald 				ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
283769b5a878SDan McDonald 				goto out;
283869b5a878SDan McDonald 			}
283969b5a878SDan McDonald 		}
284069b5a878SDan McDonald 	}
284169b5a878SDan McDonald 
284269b5a878SDan McDonald 	/* Negotiate the fc mode to use */
2843*48ed61a7SRobert Mustacchi 	hw->mac.ops.fc_autoneg(hw);
284473cd555cSBin Tu - Sun Microsystems - Beijing China 
284573cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Disable any previous flow control settings */
284673cd555cSBin Tu - Sun Microsystems - Beijing China 	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
284769b5a878SDan McDonald 	mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
284873cd555cSBin Tu - Sun Microsystems - Beijing China 
284973cd555cSBin Tu - Sun Microsystems - Beijing China 	fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
285073cd555cSBin Tu - Sun Microsystems - Beijing China 	fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
285173cd555cSBin Tu - Sun Microsystems - Beijing China 
285273cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
285373cd555cSBin Tu - Sun Microsystems - Beijing China 	 * The possible values of fc.current_mode are:
285473cd555cSBin Tu - Sun Microsystems - Beijing China 	 * 0: Flow control is completely disabled
285573cd555cSBin Tu - Sun Microsystems - Beijing China 	 * 1: Rx flow control is enabled (we can receive pause frames,
285673cd555cSBin Tu - Sun Microsystems - Beijing China 	 *    but not send pause frames).
285773cd555cSBin Tu - Sun Microsystems - Beijing China 	 * 2: Tx flow control is enabled (we can send pause frames but
285873cd555cSBin Tu - Sun Microsystems - Beijing China 	 *    we do not support receiving pause frames).
285973cd555cSBin Tu - Sun Microsystems - Beijing China 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
286073cd555cSBin Tu - Sun Microsystems - Beijing China 	 * other: Invalid.
286173cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
286273cd555cSBin Tu - Sun Microsystems - Beijing China 	switch (hw->fc.current_mode) {
286373cd555cSBin Tu - Sun Microsystems - Beijing China 	case ixgbe_fc_none:
286473cd555cSBin Tu - Sun Microsystems - Beijing China 		/*
286573cd555cSBin Tu - Sun Microsystems - Beijing China 		 * Flow control is disabled by software override or autoneg.
286673cd555cSBin Tu - Sun Microsystems - Beijing China 		 * The code below will actually disable it in the HW.
286773cd555cSBin Tu - Sun Microsystems - Beijing China 		 */
286873cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
286973cd555cSBin Tu - Sun Microsystems - Beijing China 	case ixgbe_fc_rx_pause:
287073cd555cSBin Tu - Sun Microsystems - Beijing China 		/*
287173cd555cSBin Tu - Sun Microsystems - Beijing China 		 * Rx Flow control is enabled and Tx Flow control is
287273cd555cSBin Tu - Sun Microsystems - Beijing China 		 * disabled by software override. Since there really
287373cd555cSBin Tu - Sun Microsystems - Beijing China 		 * isn't a way to advertise that we are capable of RX
287473cd555cSBin Tu - Sun Microsystems - Beijing China 		 * Pause ONLY, we will advertise that we support both
287573cd555cSBin Tu - Sun Microsystems - Beijing China 		 * symmetric and asymmetric Rx PAUSE.  Later, we will
287673cd555cSBin Tu - Sun Microsystems - Beijing China 		 * disable the adapter's ability to send PAUSE frames.
287773cd555cSBin Tu - Sun Microsystems - Beijing China 		 */
287873cd555cSBin Tu - Sun Microsystems - Beijing China 		mflcn_reg |= IXGBE_MFLCN_RFCE;
287973cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
288073cd555cSBin Tu - Sun Microsystems - Beijing China 	case ixgbe_fc_tx_pause:
288173cd555cSBin Tu - Sun Microsystems - Beijing China 		/*
288273cd555cSBin Tu - Sun Microsystems - Beijing China 		 * Tx Flow control is enabled, and Rx Flow control is
288373cd555cSBin Tu - Sun Microsystems - Beijing China 		 * disabled by software override.
288473cd555cSBin Tu - Sun Microsystems - Beijing China 		 */
288573cd555cSBin Tu - Sun Microsystems - Beijing China 		fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
288673cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
288773cd555cSBin Tu - Sun Microsystems - Beijing China 	case ixgbe_fc_full:
288873cd555cSBin Tu - Sun Microsystems - Beijing China 		/* Flow control (both Rx and Tx) is enabled by SW override. */
288973cd555cSBin Tu - Sun Microsystems - Beijing China 		mflcn_reg |= IXGBE_MFLCN_RFCE;
289073cd555cSBin Tu - Sun Microsystems - Beijing China 		fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
289173cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
289273cd555cSBin Tu - Sun Microsystems - Beijing China 	default:
2893dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_ARGUMENT,
2894dc0cb1cdSDale Ghent 			     "Flow control param set incorrectly\n");
28953cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		ret_val = IXGBE_ERR_CONFIG;
289673cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
2897dc0cb1cdSDale Ghent 		break;
289873cd555cSBin Tu - Sun Microsystems - Beijing China 	}
289973cd555cSBin Tu - Sun Microsystems - Beijing China 
290073cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Set 802.3x based flow control settings. */
290173cd555cSBin Tu - Sun Microsystems - Beijing China 	mflcn_reg |= IXGBE_MFLCN_DPF;
290273cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
290373cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
290473cd555cSBin Tu - Sun Microsystems - Beijing China 
2905185c5677SPaul Guo 
290669b5a878SDan McDonald 	/* Set up and enable Rx high/low water mark thresholds, enable XON. */
290769b5a878SDan McDonald 	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
290869b5a878SDan McDonald 		if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
290969b5a878SDan McDonald 		    hw->fc.high_water[i]) {
291069b5a878SDan McDonald 			fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
291169b5a878SDan McDonald 			IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
291269b5a878SDan McDonald 			fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
291369b5a878SDan McDonald 		} else {
291469b5a878SDan McDonald 			IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
291569b5a878SDan McDonald 			/*
291669b5a878SDan McDonald 			 * In order to prevent Tx hangs when the internal Tx
291769b5a878SDan McDonald 			 * switch is enabled we must set the high water mark
2918dc0cb1cdSDale Ghent 			 * to the Rx packet buffer size - 24KB.  This allows
2919dc0cb1cdSDale Ghent 			 * the Tx switch to function even under heavy Rx
2920dc0cb1cdSDale Ghent 			 * workloads.
292169b5a878SDan McDonald 			 */
2922dc0cb1cdSDale Ghent 			fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576;
292369b5a878SDan McDonald 		}
292473cd555cSBin Tu - Sun Microsystems - Beijing China 
292569b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
292673cd555cSBin Tu - Sun Microsystems - Beijing China 	}
292773cd555cSBin Tu - Sun Microsystems - Beijing China 
292873cd555cSBin Tu - Sun Microsystems - Beijing China 	/* Configure pause time (2 TCs per register) */
292969b5a878SDan McDonald 	reg = hw->fc.pause_time * 0x00010001;
293069b5a878SDan McDonald 	for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++)
293169b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
293273cd555cSBin Tu - Sun Microsystems - Beijing China 
293369b5a878SDan McDonald 	/* Configure flow control refresh threshold value */
293469b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
293573cd555cSBin Tu - Sun Microsystems - Beijing China 
293673cd555cSBin Tu - Sun Microsystems - Beijing China out:
293763b3bba8SJerry Jelinek 	return ret_val;
293873cd555cSBin Tu - Sun Microsystems - Beijing China }
293973cd555cSBin Tu - Sun Microsystems - Beijing China 
294063b3bba8SJerry Jelinek /**
294169b5a878SDan McDonald  *  ixgbe_negotiate_fc - Negotiate flow control
294263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
294369b5a878SDan McDonald  *  @adv_reg: flow control advertised settings
294469b5a878SDan McDonald  *  @lp_reg: link partner's flow control settings
294569b5a878SDan McDonald  *  @adv_sym: symmetric pause bit in advertisement
294669b5a878SDan McDonald  *  @adv_asm: asymmetric pause bit in advertisement
294769b5a878SDan McDonald  *  @lp_sym: symmetric pause bit in link partner advertisement
294869b5a878SDan McDonald  *  @lp_asm: asymmetric pause bit in link partner advertisement
294973cd555cSBin Tu - Sun Microsystems - Beijing China  *
295069b5a878SDan McDonald  *  Find the intersection between advertised settings and link partner's
295169b5a878SDan McDonald  *  advertised settings
295263b3bba8SJerry Jelinek  **/
ixgbe_negotiate_fc(struct ixgbe_hw * hw,u32 adv_reg,u32 lp_reg,u32 adv_sym,u32 adv_asm,u32 lp_sym,u32 lp_asm)2953*48ed61a7SRobert Mustacchi s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
2954*48ed61a7SRobert Mustacchi 		       u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
295573cd555cSBin Tu - Sun Microsystems - Beijing China {
2956dc0cb1cdSDale Ghent 	if ((!(adv_reg)) ||  (!(lp_reg))) {
2957dc0cb1cdSDale Ghent 		ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED,
2958dc0cb1cdSDale Ghent 			     "Local or link partner's advertised flow control "
2959dc0cb1cdSDale Ghent 			     "settings are NULL. Local: %x, link partner: %x\n",
2960dc0cb1cdSDale Ghent 			     adv_reg, lp_reg);
296169b5a878SDan McDonald 		return IXGBE_ERR_FC_NOT_NEGOTIATED;
2962dc0cb1cdSDale Ghent 	}
29635b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
296469b5a878SDan McDonald 	if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
296569b5a878SDan McDonald 		/*
296669b5a878SDan McDonald 		 * Now we need to check if the user selected Rx ONLY
296769b5a878SDan McDonald 		 * of pause frames.  In this case, we had to advertise
296869b5a878SDan McDonald 		 * FULL flow control because we could not advertise RX
296969b5a878SDan McDonald 		 * ONLY. Hence, we must now check to see if we need to
297069b5a878SDan McDonald 		 * turn OFF the TRANSMISSION of PAUSE frames.
297169b5a878SDan McDonald 		 */
297269b5a878SDan McDonald 		if (hw->fc.requested_mode == ixgbe_fc_full) {
297369b5a878SDan McDonald 			hw->fc.current_mode = ixgbe_fc_full;
297469b5a878SDan McDonald 			DEBUGOUT("Flow Control = FULL.\n");
297569b5a878SDan McDonald 		} else {
297669b5a878SDan McDonald 			hw->fc.current_mode = ixgbe_fc_rx_pause;
297769b5a878SDan McDonald 			DEBUGOUT("Flow Control=RX PAUSE frames only\n");
297869b5a878SDan McDonald 		}
297969b5a878SDan McDonald 	} else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
298069b5a878SDan McDonald 		   (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
298169b5a878SDan McDonald 		hw->fc.current_mode = ixgbe_fc_tx_pause;
298269b5a878SDan McDonald 		DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
298369b5a878SDan McDonald 	} else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
298469b5a878SDan McDonald 		   !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
298569b5a878SDan McDonald 		hw->fc.current_mode = ixgbe_fc_rx_pause;
298669b5a878SDan McDonald 		DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
29875b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	} else {
298869b5a878SDan McDonald 		hw->fc.current_mode = ixgbe_fc_none;
298969b5a878SDan McDonald 		DEBUGOUT("Flow Control = NONE.\n");
29903cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
299169b5a878SDan McDonald 	return IXGBE_SUCCESS;
29925b6dd21fSchenlu chen - Sun Microsystems - Beijing China }
29935b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
299463b3bba8SJerry Jelinek /**
299563b3bba8SJerry Jelinek  *  ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
299663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
29975b6dd21fSchenlu chen - Sun Microsystems - Beijing China  *
299863b3bba8SJerry Jelinek  *  Enable flow control according on 1 gig fiber.
299963b3bba8SJerry Jelinek  **/
ixgbe_fc_autoneg_fiber(struct ixgbe_hw * hw)300063b3bba8SJerry Jelinek static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
30015b6dd21fSchenlu chen - Sun Microsystems - Beijing China {
30025b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
300369b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
30043cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
30053cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
30063cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * On multispeed fiber at 1g, bail out if
30073cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * - link is up but AN did not complete, or if
30083cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * - link is up and AN completed but timed out
30093cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
30105b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
30115b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
301269b5a878SDan McDonald 	if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
3013dc0cb1cdSDale Ghent 	    (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
3014dc0cb1cdSDale Ghent 		DEBUGOUT("Auto-Negotiation did not complete or timed out\n");
30155b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		goto out;
3016dc0cb1cdSDale Ghent 	}
30173cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
30185b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
30195b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
30205b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
302163b3bba8SJerry Jelinek 	ret_val =  ixgbe_negotiate_fc(hw, pcs_anadv_reg,
302269b5a878SDan McDonald 				      pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE,
302369b5a878SDan McDonald 				      IXGBE_PCS1GANA_ASM_PAUSE,
302469b5a878SDan McDonald 				      IXGBE_PCS1GANA_SYM_PAUSE,
302569b5a878SDan McDonald 				      IXGBE_PCS1GANA_ASM_PAUSE);
30265b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
30275b6dd21fSchenlu chen - Sun Microsystems - Beijing China out:
302863b3bba8SJerry Jelinek 	return ret_val;
30295b6dd21fSchenlu chen - Sun Microsystems - Beijing China }
30305b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
303163b3bba8SJerry Jelinek /**
303263b3bba8SJerry Jelinek  *  ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37
303363b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
30345b6dd21fSchenlu chen - Sun Microsystems - Beijing China  *
303563b3bba8SJerry Jelinek  *  Enable flow control according to IEEE clause 37.
303663b3bba8SJerry Jelinek  **/
ixgbe_fc_autoneg_backplane(struct ixgbe_hw * hw)303763b3bba8SJerry Jelinek static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
30385b6dd21fSchenlu chen - Sun Microsystems - Beijing China {
30395b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	u32 links2, anlp1_reg, autoc_reg, links;
304069b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
30415b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
30423cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
30435b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * On backplane, bail out if
30445b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * - backplane autoneg was not completed, or if
30455b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * - we are 82599 and link partner is not AN enabled
30463cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
30475b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	links = IXGBE_READ_REG(hw, IXGBE_LINKS);
3048dc0cb1cdSDale Ghent 	if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
3049dc0cb1cdSDale Ghent 		DEBUGOUT("Auto-Negotiation did not complete\n");
305073cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
3051dc0cb1cdSDale Ghent 	}
305273cd555cSBin Tu - Sun Microsystems - Beijing China 
30535b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (hw->mac.type == ixgbe_mac_82599EB) {
30545b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
3055dc0cb1cdSDale Ghent 		if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
3056dc0cb1cdSDale Ghent 			DEBUGOUT("Link partner is not AN enabled\n");
30575b6dd21fSchenlu chen - Sun Microsystems - Beijing China 			goto out;
3058dc0cb1cdSDale Ghent 		}
30595b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	}
306073cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
30615b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	 * Read the 10g AN autoc and LP ability registers and resolve
306273cd555cSBin Tu - Sun Microsystems - Beijing China 	 * local flow control settings accordingly
306373cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
30645b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
30655b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
30663cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
30675b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	ret_val = ixgbe_negotiate_fc(hw, autoc_reg,
306863b3bba8SJerry Jelinek 		anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE,
306963b3bba8SJerry Jelinek 		IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE);
30705b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
30715b6dd21fSchenlu chen - Sun Microsystems - Beijing China out:
307263b3bba8SJerry Jelinek 	return ret_val;
30735b6dd21fSchenlu chen - Sun Microsystems - Beijing China }
30745b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
307563b3bba8SJerry Jelinek /**
307663b3bba8SJerry Jelinek  *  ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37
307763b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
30785b6dd21fSchenlu chen - Sun Microsystems - Beijing China  *
307963b3bba8SJerry Jelinek  *  Enable flow control according to IEEE clause 37.
308063b3bba8SJerry Jelinek  **/
ixgbe_fc_autoneg_copper(struct ixgbe_hw * hw)308163b3bba8SJerry Jelinek static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw)
30825b6dd21fSchenlu chen - Sun Microsystems - Beijing China {
30835b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	u16 technology_ability_reg = 0;
30845b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	u16 lp_technology_ability_reg = 0;
30855b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
30865b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
308763b3bba8SJerry Jelinek 			     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
308863b3bba8SJerry Jelinek 			     &technology_ability_reg);
30895b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP,
309063b3bba8SJerry Jelinek 			     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
309163b3bba8SJerry Jelinek 			     &lp_technology_ability_reg);
309263b3bba8SJerry Jelinek 
309363b3bba8SJerry Jelinek 	return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg,
309463b3bba8SJerry Jelinek 				  (u32)lp_technology_ability_reg,
309563b3bba8SJerry Jelinek 				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE,
309663b3bba8SJerry Jelinek 				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE);
309763b3bba8SJerry Jelinek }
309863b3bba8SJerry Jelinek 
309963b3bba8SJerry Jelinek /**
310069b5a878SDan McDonald  *  ixgbe_fc_autoneg - Configure flow control
310163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
310273cd555cSBin Tu - Sun Microsystems - Beijing China  *
310369b5a878SDan McDonald  *  Compares our advertised flow control capabilities to those advertised by
310469b5a878SDan McDonald  *  our link partner, and determines the proper flow control mode to use.
310563b3bba8SJerry Jelinek  **/
ixgbe_fc_autoneg(struct ixgbe_hw * hw)310669b5a878SDan McDonald void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
310773cd555cSBin Tu - Sun Microsystems - Beijing China {
310869b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
310969b5a878SDan McDonald 	ixgbe_link_speed speed;
311069b5a878SDan McDonald 	bool link_up;
31113cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
311269b5a878SDan McDonald 	DEBUGFUNC("ixgbe_fc_autoneg");
311373cd555cSBin Tu - Sun Microsystems - Beijing China 
311473cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
311569b5a878SDan McDonald 	 * AN should have completed when the cable was plugged in.
311669b5a878SDan McDonald 	 * Look for reasons to bail out.  Bail out if:
311769b5a878SDan McDonald 	 * - FC autoneg is disabled, or if
311869b5a878SDan McDonald 	 * - link is not up.
311973cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
3120dc0cb1cdSDale Ghent 	if (hw->fc.disable_fc_autoneg) {
3121dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
3122dc0cb1cdSDale Ghent 			     "Flow control autoneg is disabled");
312373cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
3124dc0cb1cdSDale Ghent 	}
312573cd555cSBin Tu - Sun Microsystems - Beijing China 
312669b5a878SDan McDonald 	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
3127dc0cb1cdSDale Ghent 	if (!link_up) {
3128dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down");
312973cd555cSBin Tu - Sun Microsystems - Beijing China 		goto out;
3130dc0cb1cdSDale Ghent 	}
313163b3bba8SJerry Jelinek 
31325b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	switch (hw->phy.media_type) {
313369b5a878SDan McDonald 	/* Autoneg flow control on fiber adapters */
3134dc0cb1cdSDale Ghent 	case ixgbe_media_type_fiber_fixed:
3135dc0cb1cdSDale Ghent 	case ixgbe_media_type_fiber_qsfp:
31365b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	case ixgbe_media_type_fiber:
313769b5a878SDan McDonald 		if (speed == IXGBE_LINK_SPEED_1GB_FULL)
313869b5a878SDan McDonald 			ret_val = ixgbe_fc_autoneg_fiber(hw);
313969b5a878SDan McDonald 		break;
314069b5a878SDan McDonald 
314169b5a878SDan McDonald 	/* Autoneg flow control on backplane adapters */
31425b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	case ixgbe_media_type_backplane:
314369b5a878SDan McDonald 		ret_val = ixgbe_fc_autoneg_backplane(hw);
31445b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		break;
31455b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
314669b5a878SDan McDonald 	/* Autoneg flow control on copper adapters */
31475b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	case ixgbe_media_type_copper:
3148dc0cb1cdSDale Ghent 		if (ixgbe_device_supports_autoneg_fc(hw))
314969b5a878SDan McDonald 			ret_val = ixgbe_fc_autoneg_copper(hw);
31505b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		break;
31515b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
31525b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	default:
315373cd555cSBin Tu - Sun Microsystems - Beijing China 		break;
31545b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	}
31555b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
315673cd555cSBin Tu - Sun Microsystems - Beijing China out:
315769b5a878SDan McDonald 	if (ret_val == IXGBE_SUCCESS) {
315869b5a878SDan McDonald 		hw->fc.fc_was_autonegged = TRUE;
315969b5a878SDan McDonald 	} else {
316069b5a878SDan McDonald 		hw->fc.fc_was_autonegged = FALSE;
316169b5a878SDan McDonald 		hw->fc.current_mode = hw->fc.requested_mode;
316269b5a878SDan McDonald 	}
316373cd555cSBin Tu - Sun Microsystems - Beijing China }
316473cd555cSBin Tu - Sun Microsystems - Beijing China 
3165dc0cb1cdSDale Ghent /*
3166dc0cb1cdSDale Ghent  * ixgbe_pcie_timeout_poll - Return number of times to poll for completion
3167dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
3168dc0cb1cdSDale Ghent  *
3169dc0cb1cdSDale Ghent  * System-wide timeout range is encoded in PCIe Device Control2 register.
3170dc0cb1cdSDale Ghent  *
3171dc0cb1cdSDale Ghent  * Add 10% to specified maximum and return the number of times to poll for
3172dc0cb1cdSDale Ghent  * completion timeout, in units of 100 microsec.  Never return less than
3173dc0cb1cdSDale Ghent  * 800 = 80 millisec.
3174dc0cb1cdSDale Ghent  */
ixgbe_pcie_timeout_poll(struct ixgbe_hw * hw)3175dc0cb1cdSDale Ghent static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw)
3176dc0cb1cdSDale Ghent {
3177dc0cb1cdSDale Ghent 	s16 devctl2;
3178dc0cb1cdSDale Ghent 	u32 pollcnt;
3179dc0cb1cdSDale Ghent 
3180dc0cb1cdSDale Ghent 	devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2);
3181dc0cb1cdSDale Ghent 	devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK;
3182dc0cb1cdSDale Ghent 
3183dc0cb1cdSDale Ghent 	switch (devctl2) {
3184dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_65_130ms:
3185dc0cb1cdSDale Ghent 		pollcnt = 1300;		/* 130 millisec */
3186dc0cb1cdSDale Ghent 		break;
3187dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_260_520ms:
3188dc0cb1cdSDale Ghent 		pollcnt = 5200;		/* 520 millisec */
3189dc0cb1cdSDale Ghent 		break;
3190dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_1_2s:
3191dc0cb1cdSDale Ghent 		pollcnt = 20000;	/* 2 sec */
3192dc0cb1cdSDale Ghent 		break;
3193dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_4_8s:
3194dc0cb1cdSDale Ghent 		pollcnt = 80000;	/* 8 sec */
3195dc0cb1cdSDale Ghent 		break;
3196dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_17_34s:
3197dc0cb1cdSDale Ghent 		pollcnt = 34000;	/* 34 sec */
3198dc0cb1cdSDale Ghent 		break;
3199dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_50_100us:	/* 100 microsecs */
3200dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_1_2ms:		/* 2 millisecs */
3201dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_16_32ms:		/* 32 millisec */
3202dc0cb1cdSDale Ghent 	case IXGBE_PCIDEVCTRL2_16_32ms_def:	/* 32 millisec default */
3203dc0cb1cdSDale Ghent 	default:
3204dc0cb1cdSDale Ghent 		pollcnt = 800;		/* 80 millisec minimum */
3205dc0cb1cdSDale Ghent 		break;
3206dc0cb1cdSDale Ghent 	}
3207dc0cb1cdSDale Ghent 
3208dc0cb1cdSDale Ghent 	/* add 10% to spec maximum */
3209dc0cb1cdSDale Ghent 	return (pollcnt * 11) / 10;
3210dc0cb1cdSDale Ghent }
3211dc0cb1cdSDale Ghent 
321263b3bba8SJerry Jelinek /**
321363b3bba8SJerry Jelinek  *  ixgbe_disable_pcie_master - Disable PCI-express master access
321463b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
32159da57d7bSbt  *
321663b3bba8SJerry Jelinek  *  Disables PCI-Express master access and verifies there are no pending
321763b3bba8SJerry Jelinek  *  requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
321863b3bba8SJerry Jelinek  *  bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS
321963b3bba8SJerry Jelinek  *  is returned signifying master requests disabled.
322063b3bba8SJerry Jelinek  **/
ixgbe_disable_pcie_master(struct ixgbe_hw * hw)322163b3bba8SJerry Jelinek s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
32229da57d7bSbt {
322319843f01SPaul Guo 	s32 status = IXGBE_SUCCESS;
3224dc0cb1cdSDale Ghent 	u32 i, poll;
3225dc0cb1cdSDale Ghent 	u16 value;
32269da57d7bSbt 
322769b5a878SDan McDonald 	DEBUGFUNC("ixgbe_disable_pcie_master");
322869b5a878SDan McDonald 
322969b5a878SDan McDonald 	/* Always set this bit to ensure any future transactions are blocked */
323069b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
323169b5a878SDan McDonald 
3232dc0cb1cdSDale Ghent 	/* Exit if master requests are blocked */
3233dc0cb1cdSDale Ghent 	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
323474b989c3SRobert Mustacchi 	    IXGBE_REMOVED(hw))
323569b5a878SDan McDonald 		goto out;
32369da57d7bSbt 
323769b5a878SDan McDonald 	/* Poll for master request bit to clear */
32389da57d7bSbt 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
323919843f01SPaul Guo 		usec_delay(100);
324069b5a878SDan McDonald 		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
324169b5a878SDan McDonald 			goto out;
324219843f01SPaul Guo 	}
324319843f01SPaul Guo 
324469b5a878SDan McDonald 	/*
324569b5a878SDan McDonald 	 * Two consecutive resets are required via CTRL.RST per datasheet
324669b5a878SDan McDonald 	 * 5.2.5.3.2 Master Disable.  We set a flag to inform the reset routine
324769b5a878SDan McDonald 	 * of this need.  The first reset prevents new master requests from
324869b5a878SDan McDonald 	 * being issued by our device.  We then must wait 1usec or more for any
324969b5a878SDan McDonald 	 * remaining completions from the PCIe bus to trickle in, and then reset
325069b5a878SDan McDonald 	 * again to clear out any effects they may have had on our device.
325169b5a878SDan McDonald 	 */
325219843f01SPaul Guo 	DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
325369b5a878SDan McDonald 	hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
325419843f01SPaul Guo 
3255dc0cb1cdSDale Ghent 	if (hw->mac.type >= ixgbe_mac_X550)
3256dc0cb1cdSDale Ghent 		goto out;
3257dc0cb1cdSDale Ghent 
325819843f01SPaul Guo 	/*
325963b3bba8SJerry Jelinek 	 * Before proceeding, make sure that the PCIe block does not have
326063b3bba8SJerry Jelinek 	 * transactions pending.
326119843f01SPaul Guo 	 */
3262dc0cb1cdSDale Ghent 	poll = ixgbe_pcie_timeout_poll(hw);
3263dc0cb1cdSDale Ghent 	for (i = 0; i < poll; i++) {
32649da57d7bSbt 		usec_delay(100);
3265dc0cb1cdSDale Ghent 		value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS);
326674b989c3SRobert Mustacchi 		if (IXGBE_REMOVED(hw))
3267dc0cb1cdSDale Ghent 			goto out;
3268dc0cb1cdSDale Ghent 		if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
326969b5a878SDan McDonald 			goto out;
32709da57d7bSbt 	}
32719da57d7bSbt 
3272dc0cb1cdSDale Ghent 	ERROR_REPORT1(IXGBE_ERROR_POLLING,
3273dc0cb1cdSDale Ghent 		     "PCIe transaction pending bit also did not clear.\n");
327469b5a878SDan McDonald 	status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
327519843f01SPaul Guo 
327619843f01SPaul Guo out:
327763b3bba8SJerry Jelinek 	return status;
32789da57d7bSbt }
32799da57d7bSbt 
328063b3bba8SJerry Jelinek /**
328163b3bba8SJerry Jelinek  *  ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
328263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
328363b3bba8SJerry Jelinek  *  @mask: Mask to specify which semaphore to acquire
32849da57d7bSbt  *
328569b5a878SDan McDonald  *  Acquires the SWFW semaphore through the GSSR register for the specified
328663b3bba8SJerry Jelinek  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
328763b3bba8SJerry Jelinek  **/
ixgbe_acquire_swfw_sync(struct ixgbe_hw * hw,u32 mask)3288dc0cb1cdSDale Ghent s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask)
32899da57d7bSbt {
3290dc0cb1cdSDale Ghent 	u32 gssr = 0;
32919da57d7bSbt 	u32 swmask = mask;
32929da57d7bSbt 	u32 fwmask = mask << 5;
3293dc0cb1cdSDale Ghent 	u32 timeout = 200;
3294dc0cb1cdSDale Ghent 	u32 i;
32959da57d7bSbt 
32963cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_acquire_swfw_sync");
32973cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3298dc0cb1cdSDale Ghent 	for (i = 0; i < timeout; i++) {
329973cd555cSBin Tu - Sun Microsystems - Beijing China 		/*
3300dc0cb1cdSDale Ghent 		 * SW NVM semaphore bit is used for access to all
3301dc0cb1cdSDale Ghent 		 * SW_FW_SYNC bits (not just NVM)
330273cd555cSBin Tu - Sun Microsystems - Beijing China 		 */
33039da57d7bSbt 		if (ixgbe_get_eeprom_semaphore(hw))
330463b3bba8SJerry Jelinek 			return IXGBE_ERR_SWFW_SYNC;
33059da57d7bSbt 
33069da57d7bSbt 		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
3307dc0cb1cdSDale Ghent 		if (!(gssr & (fwmask | swmask))) {
3308dc0cb1cdSDale Ghent 			gssr |= swmask;
3309dc0cb1cdSDale Ghent 			IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
3310dc0cb1cdSDale Ghent 			ixgbe_release_eeprom_semaphore(hw);
3311dc0cb1cdSDale Ghent 			return IXGBE_SUCCESS;
3312dc0cb1cdSDale Ghent 		} else {
3313dc0cb1cdSDale Ghent 			/* Resource is currently in use by FW or SW */
3314dc0cb1cdSDale Ghent 			ixgbe_release_eeprom_semaphore(hw);
3315dc0cb1cdSDale Ghent 			msec_delay(5);
3316dc0cb1cdSDale Ghent 		}
33179da57d7bSbt 	}
33189da57d7bSbt 
3319dc0cb1cdSDale Ghent 	/* If time expired clear the bits holding the lock and retry */
3320dc0cb1cdSDale Ghent 	if (gssr & (fwmask | swmask))
3321dc0cb1cdSDale Ghent 		ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask));
33229da57d7bSbt 
3323dc0cb1cdSDale Ghent 	msec_delay(5);
3324dc0cb1cdSDale Ghent 	return IXGBE_ERR_SWFW_SYNC;
33259da57d7bSbt }
33269da57d7bSbt 
332763b3bba8SJerry Jelinek /**
332863b3bba8SJerry Jelinek  *  ixgbe_release_swfw_sync - Release SWFW semaphore
332963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
333063b3bba8SJerry Jelinek  *  @mask: Mask to specify which semaphore to release
33319da57d7bSbt  *
333269b5a878SDan McDonald  *  Releases the SWFW semaphore through the GSSR register for the specified
333363b3bba8SJerry Jelinek  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
333463b3bba8SJerry Jelinek  **/
ixgbe_release_swfw_sync(struct ixgbe_hw * hw,u32 mask)3335dc0cb1cdSDale Ghent void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask)
33369da57d7bSbt {
33379da57d7bSbt 	u32 gssr;
33389da57d7bSbt 	u32 swmask = mask;
33399da57d7bSbt 
33403cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_release_swfw_sync");
33413cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3342dc0cb1cdSDale Ghent 	ixgbe_get_eeprom_semaphore(hw);
33439da57d7bSbt 
33449da57d7bSbt 	gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
33459da57d7bSbt 	gssr &= ~swmask;
33469da57d7bSbt 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
33479da57d7bSbt 
33489da57d7bSbt 	ixgbe_release_eeprom_semaphore(hw);
33499da57d7bSbt }
335073cd555cSBin Tu - Sun Microsystems - Beijing China 
335169b5a878SDan McDonald /**
335269b5a878SDan McDonald  *  ixgbe_disable_sec_rx_path_generic - Stops the receive data path
335369b5a878SDan McDonald  *  @hw: pointer to hardware structure
335469b5a878SDan McDonald  *
335569b5a878SDan McDonald  *  Stops the receive data path and waits for the HW to internally empty
335669b5a878SDan McDonald  *  the Rx security block
335769b5a878SDan McDonald  **/
ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw * hw)335869b5a878SDan McDonald s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw)
335969b5a878SDan McDonald {
336069b5a878SDan McDonald #define IXGBE_MAX_SECRX_POLL 40
336169b5a878SDan McDonald 
336269b5a878SDan McDonald 	int i;
336369b5a878SDan McDonald 	int secrxreg;
336469b5a878SDan McDonald 
336569b5a878SDan McDonald 	DEBUGFUNC("ixgbe_disable_sec_rx_path_generic");
336669b5a878SDan McDonald 
336769b5a878SDan McDonald 
336869b5a878SDan McDonald 	secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
336969b5a878SDan McDonald 	secrxreg |= IXGBE_SECRXCTRL_RX_DIS;
337069b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
337169b5a878SDan McDonald 	for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) {
337269b5a878SDan McDonald 		secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT);
337369b5a878SDan McDonald 		if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY)
337469b5a878SDan McDonald 			break;
337569b5a878SDan McDonald 		else
337669b5a878SDan McDonald 			/* Use interrupt-safe sleep just in case */
337769b5a878SDan McDonald 			usec_delay(1000);
337869b5a878SDan McDonald 	}
337969b5a878SDan McDonald 
338069b5a878SDan McDonald 	/* For informational purposes only */
338169b5a878SDan McDonald 	if (i >= IXGBE_MAX_SECRX_POLL)
338269b5a878SDan McDonald 		DEBUGOUT("Rx unit being enabled before security "
338369b5a878SDan McDonald 			 "path fully disabled.  Continuing with init.\n");
338469b5a878SDan McDonald 
338569b5a878SDan McDonald 	return IXGBE_SUCCESS;
338669b5a878SDan McDonald }
338769b5a878SDan McDonald 
3388dc0cb1cdSDale Ghent /**
3389dc0cb1cdSDale Ghent  *  prot_autoc_read_generic - Hides MAC differences needed for AUTOC read
3390dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
3391*48ed61a7SRobert Mustacchi  *  @locked: bool to indicate whether the SW/FW lock was taken
3392dc0cb1cdSDale Ghent  *  @reg_val: Value we read from AUTOC
3393dc0cb1cdSDale Ghent  *
3394dc0cb1cdSDale Ghent  *  The default case requires no protection so just to the register read.
3395dc0cb1cdSDale Ghent  */
prot_autoc_read_generic(struct ixgbe_hw * hw,bool * locked,u32 * reg_val)3396dc0cb1cdSDale Ghent s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val)
3397dc0cb1cdSDale Ghent {
3398dc0cb1cdSDale Ghent 	*locked = FALSE;
3399dc0cb1cdSDale Ghent 	*reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
3400dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
3401dc0cb1cdSDale Ghent }
3402dc0cb1cdSDale Ghent 
3403dc0cb1cdSDale Ghent /**
3404dc0cb1cdSDale Ghent  * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write
3405dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
3406dc0cb1cdSDale Ghent  * @reg_val: value to write to AUTOC
3407dc0cb1cdSDale Ghent  * @locked: bool to indicate whether the SW/FW lock was already taken by
3408dc0cb1cdSDale Ghent  *           previous read.
3409dc0cb1cdSDale Ghent  *
3410dc0cb1cdSDale Ghent  * The default case requires no protection so just to the register write.
3411dc0cb1cdSDale Ghent  */
prot_autoc_write_generic(struct ixgbe_hw * hw,u32 reg_val,bool locked)3412dc0cb1cdSDale Ghent s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked)
3413dc0cb1cdSDale Ghent {
3414dc0cb1cdSDale Ghent 	UNREFERENCED_1PARAMETER(locked);
3415dc0cb1cdSDale Ghent 
3416dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val);
3417dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
3418dc0cb1cdSDale Ghent }
3419dc0cb1cdSDale Ghent 
342069b5a878SDan McDonald /**
342169b5a878SDan McDonald  *  ixgbe_enable_sec_rx_path_generic - Enables the receive data path
342269b5a878SDan McDonald  *  @hw: pointer to hardware structure
342369b5a878SDan McDonald  *
342469b5a878SDan McDonald  *  Enables the receive data path.
342569b5a878SDan McDonald  **/
ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw * hw)342669b5a878SDan McDonald s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw)
342769b5a878SDan McDonald {
3428*48ed61a7SRobert Mustacchi 	u32 secrxreg;
342969b5a878SDan McDonald 
343069b5a878SDan McDonald 	DEBUGFUNC("ixgbe_enable_sec_rx_path_generic");
343169b5a878SDan McDonald 
343269b5a878SDan McDonald 	secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
343369b5a878SDan McDonald 	secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS;
343469b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
343569b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
343669b5a878SDan McDonald 
343769b5a878SDan McDonald 	return IXGBE_SUCCESS;
343869b5a878SDan McDonald }
343969b5a878SDan McDonald 
344063b3bba8SJerry Jelinek /**
344163b3bba8SJerry Jelinek  *  ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
344263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
344363b3bba8SJerry Jelinek  *  @regval: register value to write to RXCTRL
344473cd555cSBin Tu - Sun Microsystems - Beijing China  *
344563b3bba8SJerry Jelinek  *  Enables the Rx DMA unit
344663b3bba8SJerry Jelinek  **/
ixgbe_enable_rx_dma_generic(struct ixgbe_hw * hw,u32 regval)344763b3bba8SJerry Jelinek s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval)
344873cd555cSBin Tu - Sun Microsystems - Beijing China {
34493cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_enable_rx_dma_generic");
34503cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3451dc0cb1cdSDale Ghent 	if (regval & IXGBE_RXCTRL_RXEN)
3452dc0cb1cdSDale Ghent 		ixgbe_enable_rx(hw);
3453dc0cb1cdSDale Ghent 	else
3454dc0cb1cdSDale Ghent 		ixgbe_disable_rx(hw);
345573cd555cSBin Tu - Sun Microsystems - Beijing China 
345663b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
345773cd555cSBin Tu - Sun Microsystems - Beijing China }
345873cd555cSBin Tu - Sun Microsystems - Beijing China 
345963b3bba8SJerry Jelinek /**
346063b3bba8SJerry Jelinek  *  ixgbe_blink_led_start_generic - Blink LED based on index.
346163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
346263b3bba8SJerry Jelinek  *  @index: led number to blink
346363b3bba8SJerry Jelinek  **/
ixgbe_blink_led_start_generic(struct ixgbe_hw * hw,u32 index)346463b3bba8SJerry Jelinek s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
346573cd555cSBin Tu - Sun Microsystems - Beijing China {
346673cd555cSBin Tu - Sun Microsystems - Beijing China 	ixgbe_link_speed speed = 0;
346773cd555cSBin Tu - Sun Microsystems - Beijing China 	bool link_up = 0;
3468dc0cb1cdSDale Ghent 	u32 autoc_reg = 0;
346973cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
3470dc0cb1cdSDale Ghent 	s32 ret_val = IXGBE_SUCCESS;
3471dc0cb1cdSDale Ghent 	bool locked = FALSE;
347273cd555cSBin Tu - Sun Microsystems - Beijing China 
34733cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_blink_led_start_generic");
34743cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3475*48ed61a7SRobert Mustacchi 	if (index > 3)
3476*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_PARAM;
3477*48ed61a7SRobert Mustacchi 
347873cd555cSBin Tu - Sun Microsystems - Beijing China 	/*
347973cd555cSBin Tu - Sun Microsystems - Beijing China 	 * Link must be up to auto-blink the LEDs;
348073cd555cSBin Tu - Sun Microsystems - Beijing China 	 * Force it if link is down.
348173cd555cSBin Tu - Sun Microsystems - Beijing China 	 */
348263b3bba8SJerry Jelinek 	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
348373cd555cSBin Tu - Sun Microsystems - Beijing China 
348473cd555cSBin Tu - Sun Microsystems - Beijing China 	if (!link_up) {
3485dc0cb1cdSDale Ghent 		ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
3486dc0cb1cdSDale Ghent 		if (ret_val != IXGBE_SUCCESS)
3487dc0cb1cdSDale Ghent 			goto out;
3488dc0cb1cdSDale Ghent 
3489185c5677SPaul Guo 		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
349073cd555cSBin Tu - Sun Microsystems - Beijing China 		autoc_reg |= IXGBE_AUTOC_FLU;
3491dc0cb1cdSDale Ghent 
3492dc0cb1cdSDale Ghent 		ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
3493dc0cb1cdSDale Ghent 		if (ret_val != IXGBE_SUCCESS)
3494dc0cb1cdSDale Ghent 			goto out;
3495dc0cb1cdSDale Ghent 
349669b5a878SDan McDonald 		IXGBE_WRITE_FLUSH(hw);
349773cd555cSBin Tu - Sun Microsystems - Beijing China 		msec_delay(10);
349873cd555cSBin Tu - Sun Microsystems - Beijing China 	}
349973cd555cSBin Tu - Sun Microsystems - Beijing China 
350073cd555cSBin Tu - Sun Microsystems - Beijing China 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
350173cd555cSBin Tu - Sun Microsystems - Beijing China 	led_reg |= IXGBE_LED_BLINK(index);
350273cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
350373cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
350473cd555cSBin Tu - Sun Microsystems - Beijing China 
3505dc0cb1cdSDale Ghent out:
3506dc0cb1cdSDale Ghent 	return ret_val;
350773cd555cSBin Tu - Sun Microsystems - Beijing China }
350873cd555cSBin Tu - Sun Microsystems - Beijing China 
350963b3bba8SJerry Jelinek /**
351063b3bba8SJerry Jelinek  *  ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
351163b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
351263b3bba8SJerry Jelinek  *  @index: led number to stop blinking
351363b3bba8SJerry Jelinek  **/
ixgbe_blink_led_stop_generic(struct ixgbe_hw * hw,u32 index)351463b3bba8SJerry Jelinek s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
351573cd555cSBin Tu - Sun Microsystems - Beijing China {
3516dc0cb1cdSDale Ghent 	u32 autoc_reg = 0;
351773cd555cSBin Tu - Sun Microsystems - Beijing China 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
3518dc0cb1cdSDale Ghent 	s32 ret_val = IXGBE_SUCCESS;
3519dc0cb1cdSDale Ghent 	bool locked = FALSE;
352073cd555cSBin Tu - Sun Microsystems - Beijing China 
35213cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_blink_led_stop_generic");
35223cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3523*48ed61a7SRobert Mustacchi 	if (index > 3)
3524*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_PARAM;
3525*48ed61a7SRobert Mustacchi 
3526dc0cb1cdSDale Ghent 	ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
3527dc0cb1cdSDale Ghent 	if (ret_val != IXGBE_SUCCESS)
3528dc0cb1cdSDale Ghent 		goto out;
352963b3bba8SJerry Jelinek 
353073cd555cSBin Tu - Sun Microsystems - Beijing China 	autoc_reg &= ~IXGBE_AUTOC_FLU;
353173cd555cSBin Tu - Sun Microsystems - Beijing China 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
3532dc0cb1cdSDale Ghent 
3533dc0cb1cdSDale Ghent 	ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
3534dc0cb1cdSDale Ghent 	if (ret_val != IXGBE_SUCCESS)
3535dc0cb1cdSDale Ghent 		goto out;
353673cd555cSBin Tu - Sun Microsystems - Beijing China 
353773cd555cSBin Tu - Sun Microsystems - Beijing China 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
353873cd555cSBin Tu - Sun Microsystems - Beijing China 	led_reg &= ~IXGBE_LED_BLINK(index);
353973cd555cSBin Tu - Sun Microsystems - Beijing China 	led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
354073cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
354173cd555cSBin Tu - Sun Microsystems - Beijing China 	IXGBE_WRITE_FLUSH(hw);
354273cd555cSBin Tu - Sun Microsystems - Beijing China 
3543dc0cb1cdSDale Ghent out:
3544dc0cb1cdSDale Ghent 	return ret_val;
354573cd555cSBin Tu - Sun Microsystems - Beijing China }
35463cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
354763b3bba8SJerry Jelinek /**
354863b3bba8SJerry Jelinek  *  ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
354963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
355063b3bba8SJerry Jelinek  *  @san_mac_offset: SAN MAC address offset
35513cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
355263b3bba8SJerry Jelinek  *  This function will read the EEPROM location for the SAN MAC address
355363b3bba8SJerry Jelinek  *  pointer, and returns the value at that location.  This is used in both
355463b3bba8SJerry Jelinek  *  get and set mac_addr routines.
355563b3bba8SJerry Jelinek  **/
ixgbe_get_san_mac_addr_offset(struct ixgbe_hw * hw,u16 * san_mac_offset)355663b3bba8SJerry Jelinek static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
355769b5a878SDan McDonald 					 u16 *san_mac_offset)
35583cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
3559dc0cb1cdSDale Ghent 	s32 ret_val;
3560dc0cb1cdSDale Ghent 
35613cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_san_mac_addr_offset");
35623cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
35633cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
35643cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * First read the EEPROM pointer to see if the MAC addresses are
35653cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * available.
35663cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
3567dc0cb1cdSDale Ghent 	ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR,
3568dc0cb1cdSDale Ghent 				      san_mac_offset);
3569dc0cb1cdSDale Ghent 	if (ret_val) {
3570dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
3571dc0cb1cdSDale Ghent 			      "eeprom at offset %d failed",
3572dc0cb1cdSDale Ghent 			      IXGBE_SAN_MAC_ADDR_PTR);
3573dc0cb1cdSDale Ghent 	}
35743cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3575dc0cb1cdSDale Ghent 	return ret_val;
35763cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
35773cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
357863b3bba8SJerry Jelinek /**
357963b3bba8SJerry Jelinek  *  ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM
358063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
358163b3bba8SJerry Jelinek  *  @san_mac_addr: SAN MAC address
35823cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
358363b3bba8SJerry Jelinek  *  Reads the SAN MAC address from the EEPROM, if it's available.  This is
358463b3bba8SJerry Jelinek  *  per-port, so set_lan_id() must be called before reading the addresses.
358563b3bba8SJerry Jelinek  *  set_lan_id() is called by identify_sfp(), but this cannot be relied
358663b3bba8SJerry Jelinek  *  upon for non-SFP connections, so we must call it here.
358763b3bba8SJerry Jelinek  **/
ixgbe_get_san_mac_addr_generic(struct ixgbe_hw * hw,u8 * san_mac_addr)358863b3bba8SJerry Jelinek s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
35893cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
35903cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u16 san_mac_data, san_mac_offset;
35913cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u8 i;
3592dc0cb1cdSDale Ghent 	s32 ret_val;
35933cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
35943cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_san_mac_addr_generic");
35953cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
35963cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
35973cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * First read the EEPROM pointer to see if the MAC addresses are
35983cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * available.  If they're not, no point in calling set_lan_id() here.
35993cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
3600dc0cb1cdSDale Ghent 	ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
3601dc0cb1cdSDale Ghent 	if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF)
36023cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		goto san_mac_addr_out;
36033cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
36043cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* make sure we know which port we need to program */
36053cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	hw->mac.ops.set_lan_id(hw);
36063cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* apply the port offset to the address offset */
36073cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	(hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
360869b5a878SDan McDonald 			 (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
36093cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (i = 0; i < 3; i++) {
3610dc0cb1cdSDale Ghent 		ret_val = hw->eeprom.ops.read(hw, san_mac_offset,
3611dc0cb1cdSDale Ghent 					      &san_mac_data);
3612dc0cb1cdSDale Ghent 		if (ret_val) {
3613dc0cb1cdSDale Ghent 			ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
3614dc0cb1cdSDale Ghent 				      "eeprom read at offset %d failed",
3615dc0cb1cdSDale Ghent 				      san_mac_offset);
3616dc0cb1cdSDale Ghent 			goto san_mac_addr_out;
3617dc0cb1cdSDale Ghent 		}
36183cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		san_mac_addr[i * 2] = (u8)(san_mac_data);
36193cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
36203cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		san_mac_offset++;
36213cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
3622dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
36233cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
36243cfa0eb9Schenlu chen - Sun Microsystems - Beijing China san_mac_addr_out:
3625dc0cb1cdSDale Ghent 	/*
3626dc0cb1cdSDale Ghent 	 * No addresses available in this EEPROM.  It's not an
3627dc0cb1cdSDale Ghent 	 * error though, so just wipe the local address and return.
3628dc0cb1cdSDale Ghent 	 */
3629dc0cb1cdSDale Ghent 	for (i = 0; i < 6; i++)
3630dc0cb1cdSDale Ghent 		san_mac_addr[i] = 0xFF;
363163b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
36323cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
36333cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
363463b3bba8SJerry Jelinek /**
363563b3bba8SJerry Jelinek  *  ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM
363663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
363763b3bba8SJerry Jelinek  *  @san_mac_addr: SAN MAC address
36383cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
363963b3bba8SJerry Jelinek  *  Write a SAN MAC address to the EEPROM.
364063b3bba8SJerry Jelinek  **/
ixgbe_set_san_mac_addr_generic(struct ixgbe_hw * hw,u8 * san_mac_addr)364163b3bba8SJerry Jelinek s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
36423cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
3643dc0cb1cdSDale Ghent 	s32 ret_val;
36443cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u16 san_mac_data, san_mac_offset;
36453cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u8 i;
36463cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
36473cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_set_san_mac_addr_generic");
36483cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
36493cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* Look for SAN mac address pointer.  If not defined, return */
3650dc0cb1cdSDale Ghent 	ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
3651dc0cb1cdSDale Ghent 	if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF)
3652dc0cb1cdSDale Ghent 		return IXGBE_ERR_NO_SAN_ADDR_PTR;
36533cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
36543cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* Make sure we know which port we need to write */
36553cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	hw->mac.ops.set_lan_id(hw);
36563cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* Apply the port offset to the address offset */
36573cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	(hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
365869b5a878SDan McDonald 			 (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
36593cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
36603cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (i = 0; i < 3; i++) {
36613cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8);
36623cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		san_mac_data |= (u16)(san_mac_addr[i * 2]);
36633cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data);
36643cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		san_mac_offset++;
36653cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
36663cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3667dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
36683cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
36693cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
367063b3bba8SJerry Jelinek /**
367163b3bba8SJerry Jelinek  *  ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count
367263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
36733cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
367463b3bba8SJerry Jelinek  *  Read PCIe configuration space, and get the MSI-X vector count from
367563b3bba8SJerry Jelinek  *  the capabilities table.
367663b3bba8SJerry Jelinek  **/
ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw * hw)367769b5a878SDan McDonald u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
36783cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
367969b5a878SDan McDonald 	u16 msix_count = 1;
368069b5a878SDan McDonald 	u16 max_msix_count;
368169b5a878SDan McDonald 	u16 pcie_offset;
368269b5a878SDan McDonald 
368369b5a878SDan McDonald 	switch (hw->mac.type) {
368469b5a878SDan McDonald 	case ixgbe_mac_82598EB:
368569b5a878SDan McDonald 		pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS;
368669b5a878SDan McDonald 		max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598;
368769b5a878SDan McDonald 		break;
368869b5a878SDan McDonald 	case ixgbe_mac_82599EB:
368969b5a878SDan McDonald 	case ixgbe_mac_X540:
3690dc0cb1cdSDale Ghent 	case ixgbe_mac_X550:
3691dc0cb1cdSDale Ghent 	case ixgbe_mac_X550EM_x:
3692*48ed61a7SRobert Mustacchi 	case ixgbe_mac_X550EM_a:
369369b5a878SDan McDonald 		pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
369469b5a878SDan McDonald 		max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
369569b5a878SDan McDonald 		break;
369669b5a878SDan McDonald 	default:
369769b5a878SDan McDonald 		return msix_count;
369869b5a878SDan McDonald 	}
36993cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
37003cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_pcie_msix_count_generic");
370169b5a878SDan McDonald 	msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset);
370274b989c3SRobert Mustacchi 	if (IXGBE_REMOVED(hw))
3703dc0cb1cdSDale Ghent 		msix_count = 0;
370469b5a878SDan McDonald 	msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
37053cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
370669b5a878SDan McDonald 	/* MSI-X count is zero-based in HW */
370769b5a878SDan McDonald 	msix_count++;
370869b5a878SDan McDonald 
370969b5a878SDan McDonald 	if (msix_count > max_msix_count)
371069b5a878SDan McDonald 		msix_count = max_msix_count;
37113cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
371263b3bba8SJerry Jelinek 	return msix_count;
37133cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
37143cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
371563b3bba8SJerry Jelinek /**
371663b3bba8SJerry Jelinek  *  ixgbe_insert_mac_addr_generic - Find a RAR for this mac address
371763b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
371863b3bba8SJerry Jelinek  *  @addr: Address to put into receive address register
371963b3bba8SJerry Jelinek  *  @vmdq: VMDq pool to assign
37203cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
372163b3bba8SJerry Jelinek  *  Puts an ethernet address into a receive address register, or
3722dc0cb1cdSDale Ghent  *  finds the rar that it is already in; adds to the pool list
372363b3bba8SJerry Jelinek  **/
ixgbe_insert_mac_addr_generic(struct ixgbe_hw * hw,u8 * addr,u32 vmdq)372463b3bba8SJerry Jelinek s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
37253cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
37263cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF;
37273cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 first_empty_rar = NO_EMPTY_RAR_FOUND;
37283cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 rar;
37293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 rar_low, rar_high;
37303cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 addr_low, addr_high;
37313cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
37323cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_insert_mac_addr_generic");
37333cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
37343cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* swap bytes for HW little endian */
37353cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	addr_low  = addr[0] | (addr[1] << 8)
373663b3bba8SJerry Jelinek 			    | (addr[2] << 16)
373763b3bba8SJerry Jelinek 			    | (addr[3] << 24);
37383cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	addr_high = addr[4] | (addr[5] << 8);
37393cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
37403cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
37413cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * Either find the mac_id in rar or find the first empty space.
37423cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * rar_highwater points to just after the highest currently used
37433cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * rar in order to shorten the search.  It grows when we add a new
37443cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * rar to the top.
37453cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
37463cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (rar = 0; rar < hw->mac.rar_highwater; rar++) {
37473cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
37483cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
374963b3bba8SJerry Jelinek 		if (((IXGBE_RAH_AV & rar_high) == 0)
375063b3bba8SJerry Jelinek 		    && first_empty_rar == NO_EMPTY_RAR_FOUND) {
37513cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			first_empty_rar = rar;
37523cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		} else if ((rar_high & 0xFFFF) == addr_high) {
37533cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar));
37543cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			if (rar_low == addr_low)
37553cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 				break;    /* found it already in the rars */
37563cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		}
37573cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
37583cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
37593cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (rar < hw->mac.rar_highwater) {
37603cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		/* already there so just add to the pool bits */
3761dc0cb1cdSDale Ghent 		ixgbe_set_vmdq(hw, rar, vmdq);
37623cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	} else if (first_empty_rar != NO_EMPTY_RAR_FOUND) {
37633cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		/* stick it into first empty RAR slot we found */
37643cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		rar = first_empty_rar;
3765dc0cb1cdSDale Ghent 		ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
37663cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	} else if (rar == hw->mac.rar_highwater) {
37673cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		/* add it to the top of the list and inc the highwater mark */
3768dc0cb1cdSDale Ghent 		ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
37693cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		hw->mac.rar_highwater++;
37703cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	} else if (rar >= hw->mac.num_rar_entries) {
377163b3bba8SJerry Jelinek 		return IXGBE_ERR_INVALID_MAC_ADDR;
37723cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
37733cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
37743cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
37753cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * If we found rar[0], make sure the default pool bit (we use pool 0)
37763cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * remains cleared to be sure default pool packets will get delivered
37773cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
37783cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (rar == 0)
3779dc0cb1cdSDale Ghent 		ixgbe_clear_vmdq(hw, rar, 0);
37803cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
378163b3bba8SJerry Jelinek 	return rar;
37823cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
37833cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
378463b3bba8SJerry Jelinek /**
378563b3bba8SJerry Jelinek  *  ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address
378663b3bba8SJerry Jelinek  *  @hw: pointer to hardware struct
378763b3bba8SJerry Jelinek  *  @rar: receive address register index to disassociate
378863b3bba8SJerry Jelinek  *  @vmdq: VMDq pool index to remove from the rar
378963b3bba8SJerry Jelinek  **/
ixgbe_clear_vmdq_generic(struct ixgbe_hw * hw,u32 rar,u32 vmdq)379063b3bba8SJerry Jelinek s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
37913cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
37923cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 mpsar_lo, mpsar_hi;
37933cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 rar_entries = hw->mac.num_rar_entries;
37943cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
37953cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_clear_vmdq_generic");
37963cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
379763b3bba8SJerry Jelinek 	/* Make sure we are using a valid rar index range */
379863b3bba8SJerry Jelinek 	if (rar >= rar_entries) {
3799dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_ARGUMENT,
3800dc0cb1cdSDale Ghent 			     "RAR index %d is out of range.\n", rar);
380163b3bba8SJerry Jelinek 		return IXGBE_ERR_INVALID_ARGUMENT;
380263b3bba8SJerry Jelinek 	}
38033cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
380463b3bba8SJerry Jelinek 	mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
380563b3bba8SJerry Jelinek 	mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
38063cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
380774b989c3SRobert Mustacchi 	if (IXGBE_REMOVED(hw))
3808dc0cb1cdSDale Ghent 		goto done;
3809dc0cb1cdSDale Ghent 
381063b3bba8SJerry Jelinek 	if (!mpsar_lo && !mpsar_hi)
381163b3bba8SJerry Jelinek 		goto done;
38123cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
381363b3bba8SJerry Jelinek 	if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
381463b3bba8SJerry Jelinek 		if (mpsar_lo) {
381563b3bba8SJerry Jelinek 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
381663b3bba8SJerry Jelinek 			mpsar_lo = 0;
381763b3bba8SJerry Jelinek 		}
381863b3bba8SJerry Jelinek 		if (mpsar_hi) {
381963b3bba8SJerry Jelinek 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
382063b3bba8SJerry Jelinek 			mpsar_hi = 0;
382163b3bba8SJerry Jelinek 		}
382263b3bba8SJerry Jelinek 	} else if (vmdq < 32) {
382363b3bba8SJerry Jelinek 		mpsar_lo &= ~(1 << vmdq);
382463b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
38253cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	} else {
382663b3bba8SJerry Jelinek 		mpsar_hi &= ~(1 << (vmdq - 32));
382763b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
38283cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
38293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
383063b3bba8SJerry Jelinek 	/* was that the last pool using this rar? */
3831*48ed61a7SRobert Mustacchi 	if (mpsar_lo == 0 && mpsar_hi == 0 &&
3832*48ed61a7SRobert Mustacchi 	    rar != 0 && rar != hw->mac.san_mac_rar_index)
383363b3bba8SJerry Jelinek 		hw->mac.ops.clear_rar(hw, rar);
38343cfa0eb9Schenlu chen - Sun Microsystems - Beijing China done:
383563b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
38363cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
38373cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
383863b3bba8SJerry Jelinek /**
383963b3bba8SJerry Jelinek  *  ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address
384063b3bba8SJerry Jelinek  *  @hw: pointer to hardware struct
384163b3bba8SJerry Jelinek  *  @rar: receive address register index to associate with a VMDq index
384263b3bba8SJerry Jelinek  *  @vmdq: VMDq pool index
384363b3bba8SJerry Jelinek  **/
ixgbe_set_vmdq_generic(struct ixgbe_hw * hw,u32 rar,u32 vmdq)384463b3bba8SJerry Jelinek s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
38453cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
38463cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 mpsar;
38473cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 rar_entries = hw->mac.num_rar_entries;
38483cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
38493cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_set_vmdq_generic");
38503cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
385163b3bba8SJerry Jelinek 	/* Make sure we are using a valid rar index range */
385263b3bba8SJerry Jelinek 	if (rar >= rar_entries) {
3853dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_ARGUMENT,
3854dc0cb1cdSDale Ghent 			     "RAR index %d is out of range.\n", rar);
385563b3bba8SJerry Jelinek 		return IXGBE_ERR_INVALID_ARGUMENT;
38563cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
385763b3bba8SJerry Jelinek 
385863b3bba8SJerry Jelinek 	if (vmdq < 32) {
385963b3bba8SJerry Jelinek 		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
386063b3bba8SJerry Jelinek 		mpsar |= 1 << vmdq;
386163b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
386263b3bba8SJerry Jelinek 	} else {
386363b3bba8SJerry Jelinek 		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
386463b3bba8SJerry Jelinek 		mpsar |= 1 << (vmdq - 32);
386563b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
386663b3bba8SJerry Jelinek 	}
386763b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
38683cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
38693cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
387069b5a878SDan McDonald /**
387169b5a878SDan McDonald  *  This function should only be involved in the IOV mode.
387269b5a878SDan McDonald  *  In IOV mode, Default pool is next pool after the number of
387369b5a878SDan McDonald  *  VFs advertized and not 0.
387469b5a878SDan McDonald  *  MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index]
387569b5a878SDan McDonald  *
387669b5a878SDan McDonald  *  ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address
387769b5a878SDan McDonald  *  @hw: pointer to hardware struct
387869b5a878SDan McDonald  *  @vmdq: VMDq pool index
387969b5a878SDan McDonald  **/
ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw * hw,u32 vmdq)388069b5a878SDan McDonald s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq)
388169b5a878SDan McDonald {
388269b5a878SDan McDonald 	u32 rar = hw->mac.san_mac_rar_index;
388369b5a878SDan McDonald 
388469b5a878SDan McDonald 	DEBUGFUNC("ixgbe_set_vmdq_san_mac");
388569b5a878SDan McDonald 
388669b5a878SDan McDonald 	if (vmdq < 32) {
388769b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq);
388869b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
388969b5a878SDan McDonald 	} else {
389069b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
389169b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32));
389269b5a878SDan McDonald 	}
389369b5a878SDan McDonald 
389469b5a878SDan McDonald 	return IXGBE_SUCCESS;
389569b5a878SDan McDonald }
389669b5a878SDan McDonald 
389763b3bba8SJerry Jelinek /**
389863b3bba8SJerry Jelinek  *  ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array
389963b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
390063b3bba8SJerry Jelinek  **/
ixgbe_init_uta_tables_generic(struct ixgbe_hw * hw)390163b3bba8SJerry Jelinek s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
39023cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
39033cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	int i;
39043cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
39053cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_init_uta_tables_generic");
39063cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGOUT(" Clearing UTA\n");
39073cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
39083cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (i = 0; i < 128; i++)
39093cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
39103cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
391163b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
39123cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
39133cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
391463b3bba8SJerry Jelinek /**
391563b3bba8SJerry Jelinek  *  ixgbe_find_vlvf_slot - find the vlanid or the first empty slot
391663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
391763b3bba8SJerry Jelinek  *  @vlan: VLAN id to write to VLAN filter
3918*48ed61a7SRobert Mustacchi  *  @vlvf_bypass: TRUE to find vlanid only, FALSE returns first empty slot if
3919*48ed61a7SRobert Mustacchi  *		  vlanid not found
3920*48ed61a7SRobert Mustacchi  *
39213cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
392263b3bba8SJerry Jelinek  *  return the VLVF index where this VLAN id should be placed
39233cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
392463b3bba8SJerry Jelinek  **/
ixgbe_find_vlvf_slot(struct ixgbe_hw * hw,u32 vlan,bool vlvf_bypass)3925*48ed61a7SRobert Mustacchi s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass)
39263cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
3927*48ed61a7SRobert Mustacchi 	s32 regindex, first_empty_slot;
3928*48ed61a7SRobert Mustacchi 	u32 bits;
39293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
393019843f01SPaul Guo 	/* short cut the special case */
393119843f01SPaul Guo 	if (vlan == 0)
393263b3bba8SJerry Jelinek 		return 0;
393319843f01SPaul Guo 
3934*48ed61a7SRobert Mustacchi 	/* if vlvf_bypass is set we don't want to use an empty slot, we
3935*48ed61a7SRobert Mustacchi 	 * will simply bypass the VLVF if there are no entries present in the
3936*48ed61a7SRobert Mustacchi 	 * VLVF that contain our VLAN
3937*48ed61a7SRobert Mustacchi 	 */
3938*48ed61a7SRobert Mustacchi 	first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0;
3939*48ed61a7SRobert Mustacchi 
3940*48ed61a7SRobert Mustacchi 	/* add VLAN enable bit for comparison */
3941*48ed61a7SRobert Mustacchi 	vlan |= IXGBE_VLVF_VIEN;
3942*48ed61a7SRobert Mustacchi 
3943*48ed61a7SRobert Mustacchi 	/* Search for the vlan id in the VLVF entries. Save off the first empty
3944*48ed61a7SRobert Mustacchi 	 * slot found along the way.
3945*48ed61a7SRobert Mustacchi 	 *
3946*48ed61a7SRobert Mustacchi 	 * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1
3947*48ed61a7SRobert Mustacchi 	 */
3948*48ed61a7SRobert Mustacchi 	for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) {
39493cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
3950*48ed61a7SRobert Mustacchi 		if (bits == vlan)
3951*48ed61a7SRobert Mustacchi 			return regindex;
3952*48ed61a7SRobert Mustacchi 		if (!first_empty_slot && !bits)
39533cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			first_empty_slot = regindex;
39543cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
39553cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3956*48ed61a7SRobert Mustacchi 	/* If we are here then we didn't find the VLAN.  Return first empty
3957*48ed61a7SRobert Mustacchi 	 * slot we found during our search, else error.
3958*48ed61a7SRobert Mustacchi 	 */
3959*48ed61a7SRobert Mustacchi 	if (!first_empty_slot)
3960*48ed61a7SRobert Mustacchi 		ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n");
39613cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3962*48ed61a7SRobert Mustacchi 	return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE;
39633cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
39643cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
396563b3bba8SJerry Jelinek /**
396663b3bba8SJerry Jelinek  *  ixgbe_set_vfta_generic - Set VLAN filter table
396763b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
396863b3bba8SJerry Jelinek  *  @vlan: VLAN id to write to VLAN filter
3969*48ed61a7SRobert Mustacchi  *  @vind: VMDq output index that maps queue to VLAN id in VLVFB
3970*48ed61a7SRobert Mustacchi  *  @vlan_on: boolean flag to turn on/off VLAN
3971*48ed61a7SRobert Mustacchi  *  @vlvf_bypass: boolean flag indicating updating default pool is okay
39723cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
397363b3bba8SJerry Jelinek  *  Turn on/off specified VLAN in the VLAN filter table.
397463b3bba8SJerry Jelinek  **/
ixgbe_set_vfta_generic(struct ixgbe_hw * hw,u32 vlan,u32 vind,bool vlan_on,bool vlvf_bypass)397563b3bba8SJerry Jelinek s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
3976*48ed61a7SRobert Mustacchi 			   bool vlan_on, bool vlvf_bypass)
39773cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
3978*48ed61a7SRobert Mustacchi 	u32 regidx, vfta_delta, vfta;
3979*48ed61a7SRobert Mustacchi 	s32 ret_val;
39803cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
39813cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_set_vfta_generic");
39823cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
3983*48ed61a7SRobert Mustacchi 	if (vlan > 4095 || vind > 63)
398463b3bba8SJerry Jelinek 		return IXGBE_ERR_PARAM;
39853cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
39863cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/*
39873cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * this is a 2 part operation - first the VFTA, then the
39883cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * VLVF and VLVFB if VT Mode is set
398919843f01SPaul Guo 	 * We don't write the VFTA until we know the VLVF part succeeded.
39903cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
39913cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
399263b3bba8SJerry Jelinek 	/* Part 1
39933cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * The VFTA is a bitstring made up of 128 32-bit registers
39943cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 * that enable the particular VLAN id, much like the MTA:
39953cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 *    bits[11-5]: which register
39963cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 *    bits[4-0]:  which bit in the register
39973cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
3998*48ed61a7SRobert Mustacchi 	regidx = vlan / 32;
3999*48ed61a7SRobert Mustacchi 	vfta_delta = 1 << (vlan % 32);
4000*48ed61a7SRobert Mustacchi 	vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx));
4001*48ed61a7SRobert Mustacchi 
4002*48ed61a7SRobert Mustacchi 	/*
4003*48ed61a7SRobert Mustacchi 	 * vfta_delta represents the difference between the current value
4004*48ed61a7SRobert Mustacchi 	 * of vfta and the value we want in the register.  Since the diff
4005*48ed61a7SRobert Mustacchi 	 * is an XOR mask we can just update the vfta using an XOR
4006*48ed61a7SRobert Mustacchi 	 */
4007*48ed61a7SRobert Mustacchi 	vfta_delta &= vlan_on ? ~vfta : vfta;
4008*48ed61a7SRobert Mustacchi 	vfta ^= vfta_delta;
40093cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
401063b3bba8SJerry Jelinek 	/* Part 2
401169b5a878SDan McDonald 	 * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF
401269b5a878SDan McDonald 	 */
4013*48ed61a7SRobert Mustacchi 	ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta,
4014*48ed61a7SRobert Mustacchi 					 vfta, vlvf_bypass);
4015*48ed61a7SRobert Mustacchi 	if (ret_val != IXGBE_SUCCESS) {
4016*48ed61a7SRobert Mustacchi 		if (vlvf_bypass)
4017*48ed61a7SRobert Mustacchi 			goto vfta_update;
401869b5a878SDan McDonald 		return ret_val;
4019*48ed61a7SRobert Mustacchi 	}
402069b5a878SDan McDonald 
4021*48ed61a7SRobert Mustacchi vfta_update:
4022*48ed61a7SRobert Mustacchi 	/* Update VFTA now that we are ready for traffic */
4023*48ed61a7SRobert Mustacchi 	if (vfta_delta)
4024*48ed61a7SRobert Mustacchi 		IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta);
402569b5a878SDan McDonald 
402669b5a878SDan McDonald 	return IXGBE_SUCCESS;
402769b5a878SDan McDonald }
402869b5a878SDan McDonald 
402969b5a878SDan McDonald /**
403069b5a878SDan McDonald  *  ixgbe_set_vlvf_generic - Set VLAN Pool Filter
403169b5a878SDan McDonald  *  @hw: pointer to hardware structure
403269b5a878SDan McDonald  *  @vlan: VLAN id to write to VLAN filter
4033*48ed61a7SRobert Mustacchi  *  @vind: VMDq output index that maps queue to VLAN id in VLVFB
4034*48ed61a7SRobert Mustacchi  *  @vlan_on: boolean flag to turn on/off VLAN in VLVF
4035*48ed61a7SRobert Mustacchi  *  @vfta_delta: pointer to the difference between the current value of VFTA
4036*48ed61a7SRobert Mustacchi  *		 and the desired value
4037*48ed61a7SRobert Mustacchi  *  @vfta: the desired value of the VFTA
4038*48ed61a7SRobert Mustacchi  *  @vlvf_bypass: boolean flag indicating updating default pool is okay
403969b5a878SDan McDonald  *
404069b5a878SDan McDonald  *  Turn on/off specified bit in VLVF table.
404169b5a878SDan McDonald  **/
ixgbe_set_vlvf_generic(struct ixgbe_hw * hw,u32 vlan,u32 vind,bool vlan_on,u32 * vfta_delta,u32 vfta,bool vlvf_bypass)404269b5a878SDan McDonald s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
4043*48ed61a7SRobert Mustacchi 			   bool vlan_on, u32 *vfta_delta, u32 vfta,
4044*48ed61a7SRobert Mustacchi 			   bool vlvf_bypass)
404569b5a878SDan McDonald {
4046*48ed61a7SRobert Mustacchi 	u32 bits;
4047*48ed61a7SRobert Mustacchi 	s32 vlvf_index;
404869b5a878SDan McDonald 
404969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_set_vlvf_generic");
405069b5a878SDan McDonald 
4051*48ed61a7SRobert Mustacchi 	if (vlan > 4095 || vind > 63)
405269b5a878SDan McDonald 		return IXGBE_ERR_PARAM;
405369b5a878SDan McDonald 
405469b5a878SDan McDonald 	/* If VT Mode is set
405563b3bba8SJerry Jelinek 	 *   Either vlan_on
405663b3bba8SJerry Jelinek 	 *     make sure the vlan is in VLVF
405763b3bba8SJerry Jelinek 	 *     set the vind bit in the matching VLVFB
405863b3bba8SJerry Jelinek 	 *   Or !vlan_on
405963b3bba8SJerry Jelinek 	 *     clear the pool bit and possibly the vind
40603cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	 */
4061*48ed61a7SRobert Mustacchi 	if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE))
4062*48ed61a7SRobert Mustacchi 		return IXGBE_SUCCESS;
40633cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
4064*48ed61a7SRobert Mustacchi 	vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass);
4065*48ed61a7SRobert Mustacchi 	if (vlvf_index < 0)
4066*48ed61a7SRobert Mustacchi 		return vlvf_index;
4067*48ed61a7SRobert Mustacchi 
4068*48ed61a7SRobert Mustacchi 	bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32));
4069*48ed61a7SRobert Mustacchi 
4070*48ed61a7SRobert Mustacchi 	/* set the pool bit */
4071*48ed61a7SRobert Mustacchi 	bits |= 1 << (vind % 32);
4072*48ed61a7SRobert Mustacchi 	if (vlan_on)
4073*48ed61a7SRobert Mustacchi 		goto vlvf_update;
4074*48ed61a7SRobert Mustacchi 
4075*48ed61a7SRobert Mustacchi 	/* clear the pool bit */
4076*48ed61a7SRobert Mustacchi 	bits ^= 1 << (vind % 32);
4077*48ed61a7SRobert Mustacchi 
4078*48ed61a7SRobert Mustacchi 	if (!bits &&
4079*48ed61a7SRobert Mustacchi 	    !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) {
4080*48ed61a7SRobert Mustacchi 		/* Clear VFTA first, then disable VLVF.  Otherwise
4081*48ed61a7SRobert Mustacchi 		 * we run the risk of stray packets leaking into
4082*48ed61a7SRobert Mustacchi 		 * the PF via the default pool
408319843f01SPaul Guo 		 */
4084*48ed61a7SRobert Mustacchi 		if (*vfta_delta)
4085*48ed61a7SRobert Mustacchi 			IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta);
4086*48ed61a7SRobert Mustacchi 
4087*48ed61a7SRobert Mustacchi 		/* disable VLVF and clear remaining bit from pool */
4088*48ed61a7SRobert Mustacchi 		IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
4089*48ed61a7SRobert Mustacchi 		IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0);
4090*48ed61a7SRobert Mustacchi 
4091*48ed61a7SRobert Mustacchi 		return IXGBE_SUCCESS;
40923cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
409319843f01SPaul Guo 
4094*48ed61a7SRobert Mustacchi 	/* If there are still bits set in the VLVFB registers
4095*48ed61a7SRobert Mustacchi 	 * for the VLAN ID indicated we need to see if the
4096*48ed61a7SRobert Mustacchi 	 * caller is requesting that we clear the VFTA entry bit.
4097*48ed61a7SRobert Mustacchi 	 * If the caller has requested that we clear the VFTA
4098*48ed61a7SRobert Mustacchi 	 * entry bit but there are still pools/VFs using this VLAN
4099*48ed61a7SRobert Mustacchi 	 * ID entry then ignore the request.  We're not worried
4100*48ed61a7SRobert Mustacchi 	 * about the case where we're turning the VFTA VLAN ID
4101*48ed61a7SRobert Mustacchi 	 * entry bit on, only when requested to turn it off as
4102*48ed61a7SRobert Mustacchi 	 * there may be multiple pools and/or VFs using the
4103*48ed61a7SRobert Mustacchi 	 * VLAN ID entry.  In that case we cannot clear the
4104*48ed61a7SRobert Mustacchi 	 * VFTA bit until all pools/VFs using that VLAN ID have also
4105*48ed61a7SRobert Mustacchi 	 * been cleared.  This will be indicated by "bits" being
4106*48ed61a7SRobert Mustacchi 	 * zero.
4107*48ed61a7SRobert Mustacchi 	 */
4108*48ed61a7SRobert Mustacchi 	*vfta_delta = 0;
4109*48ed61a7SRobert Mustacchi 
4110*48ed61a7SRobert Mustacchi vlvf_update:
4111*48ed61a7SRobert Mustacchi 	/* record pool change and enable VLAN ID if not already enabled */
4112*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits);
4113*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan);
4114*48ed61a7SRobert Mustacchi 
411563b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
41163cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
41173cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
411863b3bba8SJerry Jelinek /**
411963b3bba8SJerry Jelinek  *  ixgbe_clear_vfta_generic - Clear VLAN filter table
412063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
41213cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
412263b3bba8SJerry Jelinek  *  Clears the VLAN filer table, and the VMDq index associated with the filter
412363b3bba8SJerry Jelinek  **/
ixgbe_clear_vfta_generic(struct ixgbe_hw * hw)412463b3bba8SJerry Jelinek s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
41253cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
41263cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 offset;
41273cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
41283cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_clear_vfta_generic");
41293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
41303cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (offset = 0; offset < hw->mac.vft_size; offset++)
41313cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
41323cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
41333cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
41343cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
413569b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0);
413669b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0);
41373cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
41383cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
413963b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
41403cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
41413cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
4142*48ed61a7SRobert Mustacchi /**
4143*48ed61a7SRobert Mustacchi  *  ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix
4144*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
4145*48ed61a7SRobert Mustacchi  *
4146*48ed61a7SRobert Mustacchi  *  Contains the logic to identify if we need to verify link for the
4147*48ed61a7SRobert Mustacchi  *  crosstalk fix
4148*48ed61a7SRobert Mustacchi  **/
ixgbe_need_crosstalk_fix(struct ixgbe_hw * hw)4149*48ed61a7SRobert Mustacchi static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw)
4150*48ed61a7SRobert Mustacchi {
4151*48ed61a7SRobert Mustacchi 
4152*48ed61a7SRobert Mustacchi 	/* Does FW say we need the fix */
4153*48ed61a7SRobert Mustacchi 	if (!hw->need_crosstalk_fix)
4154*48ed61a7SRobert Mustacchi 		return FALSE;
4155*48ed61a7SRobert Mustacchi 
4156*48ed61a7SRobert Mustacchi 	/* Only consider SFP+ PHYs i.e. media type fiber */
4157*48ed61a7SRobert Mustacchi 	switch (hw->mac.ops.get_media_type(hw)) {
4158*48ed61a7SRobert Mustacchi 	case ixgbe_media_type_fiber:
4159*48ed61a7SRobert Mustacchi 	case ixgbe_media_type_fiber_qsfp:
4160*48ed61a7SRobert Mustacchi 		break;
4161*48ed61a7SRobert Mustacchi 	default:
4162*48ed61a7SRobert Mustacchi 		return FALSE;
4163*48ed61a7SRobert Mustacchi 	}
4164*48ed61a7SRobert Mustacchi 
4165*48ed61a7SRobert Mustacchi 	return TRUE;
4166*48ed61a7SRobert Mustacchi }
4167*48ed61a7SRobert Mustacchi 
416863b3bba8SJerry Jelinek /**
416963b3bba8SJerry Jelinek  *  ixgbe_check_mac_link_generic - Determine link and speed status
417063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
417163b3bba8SJerry Jelinek  *  @speed: pointer to link speed
417263b3bba8SJerry Jelinek  *  @link_up: TRUE when link is up
417363b3bba8SJerry Jelinek  *  @link_up_wait_to_complete: bool used to wait for link up or not
41743cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
417563b3bba8SJerry Jelinek  *  Reads the links register to determine if link is up and the current speed
417663b3bba8SJerry Jelinek  **/
ixgbe_check_mac_link_generic(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * link_up,bool link_up_wait_to_complete)417763b3bba8SJerry Jelinek s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
417869b5a878SDan McDonald 				 bool *link_up, bool link_up_wait_to_complete)
41793cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
41805b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	u32 links_reg, links_orig;
41813cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u32 i;
41823cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
41833cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_check_mac_link_generic");
41843cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
4185*48ed61a7SRobert Mustacchi 	/* If Crosstalk fix enabled do the sanity check of making sure
4186*48ed61a7SRobert Mustacchi 	 * the SFP+ cage is full.
4187*48ed61a7SRobert Mustacchi 	 */
4188*48ed61a7SRobert Mustacchi 	if (ixgbe_need_crosstalk_fix(hw)) {
4189*48ed61a7SRobert Mustacchi 		u32 sfp_cage_full;
4190*48ed61a7SRobert Mustacchi 
4191*48ed61a7SRobert Mustacchi 		switch (hw->mac.type) {
4192*48ed61a7SRobert Mustacchi 		case ixgbe_mac_82599EB:
4193*48ed61a7SRobert Mustacchi 			sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
4194*48ed61a7SRobert Mustacchi 					IXGBE_ESDP_SDP2;
4195*48ed61a7SRobert Mustacchi 			break;
4196*48ed61a7SRobert Mustacchi 		case ixgbe_mac_X550EM_x:
4197*48ed61a7SRobert Mustacchi 		case ixgbe_mac_X550EM_a:
4198*48ed61a7SRobert Mustacchi 			sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
4199*48ed61a7SRobert Mustacchi 					IXGBE_ESDP_SDP0;
4200*48ed61a7SRobert Mustacchi 			break;
4201*48ed61a7SRobert Mustacchi 		default:
4202*48ed61a7SRobert Mustacchi 			/* sanity check - No SFP+ devices here */
4203*48ed61a7SRobert Mustacchi 			sfp_cage_full = FALSE;
4204*48ed61a7SRobert Mustacchi 			break;
4205*48ed61a7SRobert Mustacchi 		}
4206*48ed61a7SRobert Mustacchi 
4207*48ed61a7SRobert Mustacchi 		if (!sfp_cage_full) {
4208*48ed61a7SRobert Mustacchi 			*link_up = FALSE;
4209*48ed61a7SRobert Mustacchi 			*speed = IXGBE_LINK_SPEED_UNKNOWN;
4210*48ed61a7SRobert Mustacchi 			return IXGBE_SUCCESS;
4211*48ed61a7SRobert Mustacchi 		}
4212*48ed61a7SRobert Mustacchi 	}
4213*48ed61a7SRobert Mustacchi 
42145b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/* clear the old state */
42155b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
42165b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
42173cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
42185b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
42195b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (links_orig != links_reg) {
42205b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		DEBUGOUT2("LINKS changed from %08X to %08X\n",
422169b5a878SDan McDonald 			  links_orig, links_reg);
42225b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	}
42235b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
42243cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (link_up_wait_to_complete) {
4225dc0cb1cdSDale Ghent 		for (i = 0; i < hw->mac.max_link_up_time; i++) {
42263cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			if (links_reg & IXGBE_LINKS_UP) {
422763b3bba8SJerry Jelinek 				*link_up = TRUE;
42283cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 				break;
42293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			} else {
423063b3bba8SJerry Jelinek 				*link_up = FALSE;
42313cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			}
42323cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			msec_delay(100);
42333cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 			links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
42343cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		}
42353cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	} else {
42363cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		if (links_reg & IXGBE_LINKS_UP)
423763b3bba8SJerry Jelinek 			*link_up = TRUE;
42383cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		else
423963b3bba8SJerry Jelinek 			*link_up = FALSE;
42403cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	}
42413cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
4242dc0cb1cdSDale Ghent 	switch (links_reg & IXGBE_LINKS_SPEED_82599) {
4243dc0cb1cdSDale Ghent 	case IXGBE_LINKS_SPEED_10G_82599:
42443cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
4245dc0cb1cdSDale Ghent 		if (hw->mac.type >= ixgbe_mac_X550) {
4246dc0cb1cdSDale Ghent 			if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
4247dc0cb1cdSDale Ghent 				*speed = IXGBE_LINK_SPEED_2_5GB_FULL;
4248dc0cb1cdSDale Ghent 		}
4249dc0cb1cdSDale Ghent 		break;
4250dc0cb1cdSDale Ghent 	case IXGBE_LINKS_SPEED_1G_82599:
42513cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
4252dc0cb1cdSDale Ghent 		break;
4253dc0cb1cdSDale Ghent 	case IXGBE_LINKS_SPEED_100_82599:
42543cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_100_FULL;
4255*48ed61a7SRobert Mustacchi 		if (hw->mac.type == ixgbe_mac_X550) {
4256dc0cb1cdSDale Ghent 			if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
4257dc0cb1cdSDale Ghent 				*speed = IXGBE_LINK_SPEED_5GB_FULL;
4258dc0cb1cdSDale Ghent 		}
4259dc0cb1cdSDale Ghent 		break;
4260*48ed61a7SRobert Mustacchi 	case IXGBE_LINKS_SPEED_10_X550EM_A:
4261*48ed61a7SRobert Mustacchi 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
4262*48ed61a7SRobert Mustacchi 		if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
4263*48ed61a7SRobert Mustacchi 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)
4264*48ed61a7SRobert Mustacchi 			*speed = IXGBE_LINK_SPEED_10_FULL;
4265*48ed61a7SRobert Mustacchi 		break;
4266dc0cb1cdSDale Ghent 	default:
42675b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
4268dc0cb1cdSDale Ghent 	}
42693cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
427063b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
42713cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
42723cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
427363b3bba8SJerry Jelinek /**
427463b3bba8SJerry Jelinek  *  ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from
427563b3bba8SJerry Jelinek  *  the EEPROM
427663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
427763b3bba8SJerry Jelinek  *  @wwnn_prefix: the alternative WWNN prefix
427863b3bba8SJerry Jelinek  *  @wwpn_prefix: the alternative WWPN prefix
42793cfa0eb9Schenlu chen - Sun Microsystems - Beijing China  *
428063b3bba8SJerry Jelinek  *  This function will read the EEPROM from the alternative SAN MAC address
428163b3bba8SJerry Jelinek  *  block to check the support for the alternative WWNN/WWPN prefix support.
428263b3bba8SJerry Jelinek  **/
ixgbe_get_wwn_prefix_generic(struct ixgbe_hw * hw,u16 * wwnn_prefix,u16 * wwpn_prefix)428363b3bba8SJerry Jelinek s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
428469b5a878SDan McDonald 				 u16 *wwpn_prefix)
42853cfa0eb9Schenlu chen - Sun Microsystems - Beijing China {
42863cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u16 offset, caps;
42873cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	u16 alt_san_mac_blk_offset;
42883cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
42893cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_wwn_prefix_generic");
42903cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
42913cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* clear output first */
42923cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	*wwnn_prefix = 0xFFFF;
42933cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	*wwpn_prefix = 0xFFFF;
42943cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
42953cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* check if alternative SAN MAC is supported */
4296dc0cb1cdSDale Ghent 	offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR;
4297dc0cb1cdSDale Ghent 	if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset))
4298dc0cb1cdSDale Ghent 		goto wwn_prefix_err;
42993cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
43003cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if ((alt_san_mac_blk_offset == 0) ||
43013cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	    (alt_san_mac_blk_offset == 0xFFFF))
43023cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		goto wwn_prefix_out;
43033cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
43043cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* check capability in alternative san mac address block */
43053cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
4306dc0cb1cdSDale Ghent 	if (hw->eeprom.ops.read(hw, offset, &caps))
4307dc0cb1cdSDale Ghent 		goto wwn_prefix_err;
43083cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
43093cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 		goto wwn_prefix_out;
43103cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
43113cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	/* get the corresponding prefix for WWNN/WWPN */
43123cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
4313dc0cb1cdSDale Ghent 	if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) {
4314dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
4315dc0cb1cdSDale Ghent 			      "eeprom read at offset %d failed", offset);
4316dc0cb1cdSDale Ghent 	}
43173cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
43183cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
4319dc0cb1cdSDale Ghent 	if (hw->eeprom.ops.read(hw, offset, wwpn_prefix))
4320dc0cb1cdSDale Ghent 		goto wwn_prefix_err;
43213cfa0eb9Schenlu chen - Sun Microsystems - Beijing China 
43223cfa0eb9Schenlu chen - Sun Microsystems - Beijing China wwn_prefix_out:
432363b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
4324dc0cb1cdSDale Ghent 
4325dc0cb1cdSDale Ghent wwn_prefix_err:
4326dc0cb1cdSDale Ghent 	ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
4327dc0cb1cdSDale Ghent 		      "eeprom read at offset %d failed", offset);
4328dc0cb1cdSDale Ghent 	return IXGBE_SUCCESS;
43293cfa0eb9Schenlu chen - Sun Microsystems - Beijing China }
43305b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
433163b3bba8SJerry Jelinek /**
433263b3bba8SJerry Jelinek  *  ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM
433363b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
433463b3bba8SJerry Jelinek  *  @bs: the fcoe boot status
43355b6dd21fSchenlu chen - Sun Microsystems - Beijing China  *
433663b3bba8SJerry Jelinek  *  This function will read the FCOE boot status from the iSCSI FCOE block
433763b3bba8SJerry Jelinek  **/
ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw * hw,u16 * bs)433863b3bba8SJerry Jelinek s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs)
43395b6dd21fSchenlu chen - Sun Microsystems - Beijing China {
43405b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	u16 offset, caps, flags;
43415b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	s32 status;
43425b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43435b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic");
43445b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43455b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/* clear output first */
43465b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	*bs = ixgbe_fcoe_bootstatus_unavailable;
43475b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43485b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/* check if FCOE IBA block is present */
43495b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR;
43505b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	status = hw->eeprom.ops.read(hw, offset, &caps);
43515b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (status != IXGBE_SUCCESS)
43525b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		goto out;
43535b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43545b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE))
43555b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		goto out;
43565b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43575b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/* check if iSCSI FCOE block is populated */
43585b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset);
43595b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (status != IXGBE_SUCCESS)
43605b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		goto out;
43615b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43625b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if ((offset == 0) || (offset == 0xFFFF))
43635b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		goto out;
43645b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43655b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	/* read fcoe flags in iSCSI FCOE block */
43665b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET;
43675b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	status = hw->eeprom.ops.read(hw, offset, &flags);
43685b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (status != IXGBE_SUCCESS)
43695b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		goto out;
43705b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43715b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE)
43725b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		*bs = ixgbe_fcoe_bootstatus_enabled;
43735b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	else
43745b6dd21fSchenlu chen - Sun Microsystems - Beijing China 		*bs = ixgbe_fcoe_bootstatus_disabled;
43755b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
43765b6dd21fSchenlu chen - Sun Microsystems - Beijing China out:
437763b3bba8SJerry Jelinek 	return status;
43785b6dd21fSchenlu chen - Sun Microsystems - Beijing China }
43795b6dd21fSchenlu chen - Sun Microsystems - Beijing China 
438063b3bba8SJerry Jelinek /**
438163b3bba8SJerry Jelinek  *  ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
438263b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
4383*48ed61a7SRobert Mustacchi  *  @enable: enable or disable switch for MAC anti-spoofing
4384*48ed61a7SRobert Mustacchi  *  @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing
438563b3bba8SJerry Jelinek  *
438663b3bba8SJerry Jelinek  **/
ixgbe_set_mac_anti_spoofing(struct ixgbe_hw * hw,bool enable,int vf)4387*48ed61a7SRobert Mustacchi void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
438863b3bba8SJerry Jelinek {
4389*48ed61a7SRobert Mustacchi 	int vf_target_reg = vf >> 3;
4390*48ed61a7SRobert Mustacchi 	int vf_target_shift = vf % 8;
4391*48ed61a7SRobert Mustacchi 	u32 pfvfspoof;
439263b3bba8SJerry Jelinek 
439363b3bba8SJerry Jelinek 	if (hw->mac.type == ixgbe_mac_82598EB)
439463b3bba8SJerry Jelinek 		return;
439563b3bba8SJerry Jelinek 
4396*48ed61a7SRobert Mustacchi 	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
439763b3bba8SJerry Jelinek 	if (enable)
4398*48ed61a7SRobert Mustacchi 		pfvfspoof |= (1 << vf_target_shift);
4399*48ed61a7SRobert Mustacchi 	else
4400*48ed61a7SRobert Mustacchi 		pfvfspoof &= ~(1 << vf_target_shift);
4401*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
440263b3bba8SJerry Jelinek }
440363b3bba8SJerry Jelinek 
440463b3bba8SJerry Jelinek /**
440563b3bba8SJerry Jelinek  *  ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing
440663b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
440763b3bba8SJerry Jelinek  *  @enable: enable or disable switch for VLAN anti-spoofing
4408dc0cb1cdSDale Ghent  *  @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
440963b3bba8SJerry Jelinek  *
441063b3bba8SJerry Jelinek  **/
ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw * hw,bool enable,int vf)441163b3bba8SJerry Jelinek void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
441263b3bba8SJerry Jelinek {
441363b3bba8SJerry Jelinek 	int vf_target_reg = vf >> 3;
441463b3bba8SJerry Jelinek 	int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT;
441563b3bba8SJerry Jelinek 	u32 pfvfspoof;
441663b3bba8SJerry Jelinek 
441763b3bba8SJerry Jelinek 	if (hw->mac.type == ixgbe_mac_82598EB)
441863b3bba8SJerry Jelinek 		return;
441963b3bba8SJerry Jelinek 
442063b3bba8SJerry Jelinek 	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
442163b3bba8SJerry Jelinek 	if (enable)
442263b3bba8SJerry Jelinek 		pfvfspoof |= (1 << vf_target_shift);
442363b3bba8SJerry Jelinek 	else
442463b3bba8SJerry Jelinek 		pfvfspoof &= ~(1 << vf_target_shift);
442563b3bba8SJerry Jelinek 	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
442663b3bba8SJerry Jelinek }
442763b3bba8SJerry Jelinek 
442863b3bba8SJerry Jelinek /**
442963b3bba8SJerry Jelinek  *  ixgbe_get_device_caps_generic - Get additional device capabilities
443063b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
443163b3bba8SJerry Jelinek  *  @device_caps: the EEPROM word with the extra device capabilities
443263b3bba8SJerry Jelinek  *
443363b3bba8SJerry Jelinek  *  This function will read the EEPROM location for the device capabilities,
443463b3bba8SJerry Jelinek  *  and return the word through device_caps.
443563b3bba8SJerry Jelinek  **/
ixgbe_get_device_caps_generic(struct ixgbe_hw * hw,u16 * device_caps)443663b3bba8SJerry Jelinek s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps)
443763b3bba8SJerry Jelinek {
443863b3bba8SJerry Jelinek 	DEBUGFUNC("ixgbe_get_device_caps_generic");
443963b3bba8SJerry Jelinek 
444063b3bba8SJerry Jelinek 	hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
444163b3bba8SJerry Jelinek 
444263b3bba8SJerry Jelinek 	return IXGBE_SUCCESS;
444363b3bba8SJerry Jelinek }
444463b3bba8SJerry Jelinek 
444563b3bba8SJerry Jelinek /**
444663b3bba8SJerry Jelinek  *  ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering
444763b3bba8SJerry Jelinek  *  @hw: pointer to hardware structure
444863b3bba8SJerry Jelinek  *
444963b3bba8SJerry Jelinek  **/
ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw * hw)445063b3bba8SJerry Jelinek void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw)
445163b3bba8SJerry Jelinek {
445263b3bba8SJerry Jelinek 	u32 regval;
445363b3bba8SJerry Jelinek 	u32 i;
445463b3bba8SJerry Jelinek 
445563b3bba8SJerry Jelinek 	DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2");
445663b3bba8SJerry Jelinek 
445763b3bba8SJerry Jelinek 	/* Enable relaxed ordering */
445863b3bba8SJerry Jelinek 	for (i = 0; i < hw->mac.max_tx_queues; i++) {
445963b3bba8SJerry Jelinek 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
446069b5a878SDan McDonald 		regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN;
446163b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
44625b6dd21fSchenlu chen - Sun Microsystems - Beijing China 	}
446363b3bba8SJerry Jelinek 
446463b3bba8SJerry Jelinek 	for (i = 0; i < hw->mac.max_rx_queues; i++) {
446563b3bba8SJerry Jelinek 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
446669b5a878SDan McDonald 		regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN |
446769b5a878SDan McDonald 			  IXGBE_DCA_RXCTRL_HEAD_WRO_EN;
446863b3bba8SJerry Jelinek 		IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
446963b3bba8SJerry Jelinek 	}
447063b3bba8SJerry Jelinek 
44715b6dd21fSchenlu chen - Sun Microsystems - Beijing China }
447269b5a878SDan McDonald 
447369b5a878SDan McDonald /**
447469b5a878SDan McDonald  *  ixgbe_calculate_checksum - Calculate checksum for buffer
447569b5a878SDan McDonald  *  @buffer: pointer to EEPROM
447669b5a878SDan McDonald  *  @length: size of EEPROM to calculate a checksum for
447769b5a878SDan McDonald  *  Calculates the checksum for some buffer on a specified length.  The
447869b5a878SDan McDonald  *  checksum calculated is returned.
447969b5a878SDan McDonald  **/
ixgbe_calculate_checksum(u8 * buffer,u32 length)4480dc0cb1cdSDale Ghent u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
448169b5a878SDan McDonald {
448269b5a878SDan McDonald 	u32 i;
448369b5a878SDan McDonald 	u8 sum = 0;
448469b5a878SDan McDonald 
448569b5a878SDan McDonald 	DEBUGFUNC("ixgbe_calculate_checksum");
448669b5a878SDan McDonald 
448769b5a878SDan McDonald 	if (!buffer)
448869b5a878SDan McDonald 		return 0;
448969b5a878SDan McDonald 
449069b5a878SDan McDonald 	for (i = 0; i < length; i++)
449169b5a878SDan McDonald 		sum += buffer[i];
449269b5a878SDan McDonald 
449369b5a878SDan McDonald 	return (u8) (0 - sum);
449469b5a878SDan McDonald }
449569b5a878SDan McDonald 
449669b5a878SDan McDonald /**
4497*48ed61a7SRobert Mustacchi  *  ixgbe_hic_unlocked - Issue command to manageability block unlocked
449869b5a878SDan McDonald  *  @hw: pointer to the HW structure
4499*48ed61a7SRobert Mustacchi  *  @buffer: command to write and where the return status will be placed
450069b5a878SDan McDonald  *  @length: length of buffer, must be multiple of 4 bytes
4501dc0cb1cdSDale Ghent  *  @timeout: time in ms to wait for command completion
450269b5a878SDan McDonald  *
4503*48ed61a7SRobert Mustacchi  *  Communicates with the manageability block. On success return IXGBE_SUCCESS
4504*48ed61a7SRobert Mustacchi  *  else returns semaphore error when encountering an error acquiring
4505*48ed61a7SRobert Mustacchi  *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
4506*48ed61a7SRobert Mustacchi  *
4507*48ed61a7SRobert Mustacchi  *  This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held
4508*48ed61a7SRobert Mustacchi  *  by the caller.
450969b5a878SDan McDonald  **/
ixgbe_hic_unlocked(struct ixgbe_hw * hw,u32 * buffer,u32 length,u32 timeout)4510*48ed61a7SRobert Mustacchi s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length,
4511*48ed61a7SRobert Mustacchi 		       u32 timeout)
451269b5a878SDan McDonald {
4513*48ed61a7SRobert Mustacchi 	u32 hicr, i, fwsts;
4514dc0cb1cdSDale Ghent 	u16 dword_len;
451569b5a878SDan McDonald 
4516*48ed61a7SRobert Mustacchi 	DEBUGFUNC("ixgbe_hic_unlocked");
451769b5a878SDan McDonald 
4518*48ed61a7SRobert Mustacchi 	if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
4519dc0cb1cdSDale Ghent 		DEBUGOUT1("Buffer length failure buffersize=%d.\n", length);
4520dc0cb1cdSDale Ghent 		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
452169b5a878SDan McDonald 	}
4522*48ed61a7SRobert Mustacchi 
4523dc0cb1cdSDale Ghent 	/* Set bit 9 of FWSTS clearing FW reset indication */
4524dc0cb1cdSDale Ghent 	fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS);
4525dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI);
452669b5a878SDan McDonald 
452769b5a878SDan McDonald 	/* Check that the host interface is enabled. */
452869b5a878SDan McDonald 	hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
4529*48ed61a7SRobert Mustacchi 	if (!(hicr & IXGBE_HICR_EN)) {
453069b5a878SDan McDonald 		DEBUGOUT("IXGBE_HOST_EN bit disabled.\n");
4531dc0cb1cdSDale Ghent 		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
4532dc0cb1cdSDale Ghent 	}
4533dc0cb1cdSDale Ghent 
4534dc0cb1cdSDale Ghent 	/* Calculate length in DWORDs. We must be DWORD aligned */
4535*48ed61a7SRobert Mustacchi 	if (length % sizeof(u32)) {
4536dc0cb1cdSDale Ghent 		DEBUGOUT("Buffer length failure, not aligned to dword");
4537dc0cb1cdSDale Ghent 		return IXGBE_ERR_INVALID_ARGUMENT;
453869b5a878SDan McDonald 	}
453969b5a878SDan McDonald 
454069b5a878SDan McDonald 	dword_len = length >> 2;
454169b5a878SDan McDonald 
4542dc0cb1cdSDale Ghent 	/* The device driver writes the relevant command block
454369b5a878SDan McDonald 	 * into the ram area.
454469b5a878SDan McDonald 	 */
454569b5a878SDan McDonald 	for (i = 0; i < dword_len; i++)
454669b5a878SDan McDonald 		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
454769b5a878SDan McDonald 				      i, IXGBE_CPU_TO_LE32(buffer[i]));
454869b5a878SDan McDonald 
454969b5a878SDan McDonald 	/* Setting this bit tells the ARC that a new command is pending. */
455069b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
455169b5a878SDan McDonald 
4552dc0cb1cdSDale Ghent 	for (i = 0; i < timeout; i++) {
455369b5a878SDan McDonald 		hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
455469b5a878SDan McDonald 		if (!(hicr & IXGBE_HICR_C))
455569b5a878SDan McDonald 			break;
455669b5a878SDan McDonald 		msec_delay(1);
455769b5a878SDan McDonald 	}
455869b5a878SDan McDonald 
4559dc0cb1cdSDale Ghent 	/* Check command completion */
4560*48ed61a7SRobert Mustacchi 	if ((timeout && i == timeout) ||
4561dc0cb1cdSDale Ghent 	    !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) {
4562dc0cb1cdSDale Ghent 		ERROR_REPORT1(IXGBE_ERROR_CAUTION,
4563dc0cb1cdSDale Ghent 			     "Command has failed with no status valid.\n");
4564dc0cb1cdSDale Ghent 		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
456569b5a878SDan McDonald 	}
456669b5a878SDan McDonald 
4567*48ed61a7SRobert Mustacchi 	return IXGBE_SUCCESS;
4568*48ed61a7SRobert Mustacchi }
4569*48ed61a7SRobert Mustacchi 
4570*48ed61a7SRobert Mustacchi /**
4571*48ed61a7SRobert Mustacchi  *  ixgbe_host_interface_command - Issue command to manageability block
4572*48ed61a7SRobert Mustacchi  *  @hw: pointer to the HW structure
4573*48ed61a7SRobert Mustacchi  *  @buffer: contains the command to write and where the return status will
4574*48ed61a7SRobert Mustacchi  *   be placed
4575*48ed61a7SRobert Mustacchi  *  @length: length of buffer, must be multiple of 4 bytes
4576*48ed61a7SRobert Mustacchi  *  @timeout: time in ms to wait for command completion
4577*48ed61a7SRobert Mustacchi  *  @return_data: read and return data from the buffer (TRUE) or not (FALSE)
4578*48ed61a7SRobert Mustacchi  *   Needed because FW structures are big endian and decoding of
4579*48ed61a7SRobert Mustacchi  *   these fields can be 8 bit or 16 bit based on command. Decoding
4580*48ed61a7SRobert Mustacchi  *   is not easily understood without making a table of commands.
4581*48ed61a7SRobert Mustacchi  *   So we will leave this up to the caller to read back the data
4582*48ed61a7SRobert Mustacchi  *   in these cases.
4583*48ed61a7SRobert Mustacchi  *
4584*48ed61a7SRobert Mustacchi  *  Communicates with the manageability block. On success return IXGBE_SUCCESS
4585*48ed61a7SRobert Mustacchi  *  else returns semaphore error when encountering an error acquiring
4586*48ed61a7SRobert Mustacchi  *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
4587*48ed61a7SRobert Mustacchi  **/
ixgbe_host_interface_command(struct ixgbe_hw * hw,u32 * buffer,u32 length,u32 timeout,bool return_data)4588*48ed61a7SRobert Mustacchi s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
4589*48ed61a7SRobert Mustacchi 				 u32 length, u32 timeout, bool return_data)
4590*48ed61a7SRobert Mustacchi {
4591*48ed61a7SRobert Mustacchi 	u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
4592*48ed61a7SRobert Mustacchi 	struct ixgbe_hic_hdr *resp = (struct ixgbe_hic_hdr *)buffer;
4593*48ed61a7SRobert Mustacchi 	u16 buf_len;
4594*48ed61a7SRobert Mustacchi 	s32 status;
4595*48ed61a7SRobert Mustacchi 	u32 bi;
4596*48ed61a7SRobert Mustacchi 	u32 dword_len;
4597*48ed61a7SRobert Mustacchi 
4598*48ed61a7SRobert Mustacchi 	DEBUGFUNC("ixgbe_host_interface_command");
4599*48ed61a7SRobert Mustacchi 
4600*48ed61a7SRobert Mustacchi 	if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
4601*48ed61a7SRobert Mustacchi 		DEBUGOUT1("Buffer length failure buffersize=%d.\n", length);
4602*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
4603*48ed61a7SRobert Mustacchi 	}
4604*48ed61a7SRobert Mustacchi 
4605*48ed61a7SRobert Mustacchi 	/* Take management host interface semaphore */
4606*48ed61a7SRobert Mustacchi 	status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
4607*48ed61a7SRobert Mustacchi 	if (status)
4608*48ed61a7SRobert Mustacchi 		return status;
4609*48ed61a7SRobert Mustacchi 
4610*48ed61a7SRobert Mustacchi 	status = ixgbe_hic_unlocked(hw, buffer, length, timeout);
4611*48ed61a7SRobert Mustacchi 	if (status)
4612*48ed61a7SRobert Mustacchi 		goto rel_out;
4613*48ed61a7SRobert Mustacchi 
4614dc0cb1cdSDale Ghent 	if (!return_data)
4615*48ed61a7SRobert Mustacchi 		goto rel_out;
4616dc0cb1cdSDale Ghent 
461769b5a878SDan McDonald 	/* Calculate length in DWORDs */
461869b5a878SDan McDonald 	dword_len = hdr_size >> 2;
461969b5a878SDan McDonald 
462069b5a878SDan McDonald 	/* first pull in the header so we know the buffer length */
462169b5a878SDan McDonald 	for (bi = 0; bi < dword_len; bi++) {
462269b5a878SDan McDonald 		buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi);
4623*48ed61a7SRobert Mustacchi 		IXGBE_LE32_TO_CPUS(&buffer[bi]);
462469b5a878SDan McDonald 	}
462569b5a878SDan McDonald 
4626*48ed61a7SRobert Mustacchi 	/*
4627*48ed61a7SRobert Mustacchi 	 * If there is any thing in data position pull it in
4628*48ed61a7SRobert Mustacchi 	 * Read Flash command requires reading buffer length from
4629*48ed61a7SRobert Mustacchi 	 * two byes instead of one byte
4630*48ed61a7SRobert Mustacchi 	 */
4631*48ed61a7SRobert Mustacchi 	if (resp->cmd == 0x30) {
4632*48ed61a7SRobert Mustacchi 		for (; bi < dword_len + 2; bi++) {
4633*48ed61a7SRobert Mustacchi 			buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
4634*48ed61a7SRobert Mustacchi 							  bi);
4635*48ed61a7SRobert Mustacchi 			IXGBE_LE32_TO_CPUS(&buffer[bi]);
4636*48ed61a7SRobert Mustacchi 		}
4637*48ed61a7SRobert Mustacchi 		buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3)
4638*48ed61a7SRobert Mustacchi 				  & 0xF00) | resp->buf_len;
4639*48ed61a7SRobert Mustacchi 		hdr_size += (2 << 2);
4640*48ed61a7SRobert Mustacchi 	} else {
4641*48ed61a7SRobert Mustacchi 		buf_len = resp->buf_len;
4642*48ed61a7SRobert Mustacchi 	}
4643*48ed61a7SRobert Mustacchi 	if (!buf_len)
4644*48ed61a7SRobert Mustacchi 		goto rel_out;
464569b5a878SDan McDonald 
4646dc0cb1cdSDale Ghent 	if (length < buf_len + hdr_size) {
464769b5a878SDan McDonald 		DEBUGOUT("Buffer not large enough for reply message.\n");
4648*48ed61a7SRobert Mustacchi 		status = IXGBE_ERR_HOST_INTERFACE_COMMAND;
4649*48ed61a7SRobert Mustacchi 		goto rel_out;
465069b5a878SDan McDonald 	}
465169b5a878SDan McDonald 
465269b5a878SDan McDonald 	/* Calculate length in DWORDs, add 3 for odd lengths */
465369b5a878SDan McDonald 	dword_len = (buf_len + 3) >> 2;
465469b5a878SDan McDonald 
4655dc0cb1cdSDale Ghent 	/* Pull in the rest of the buffer (bi is where we left off) */
465669b5a878SDan McDonald 	for (; bi <= dword_len; bi++) {
465769b5a878SDan McDonald 		buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi);
4658*48ed61a7SRobert Mustacchi 		IXGBE_LE32_TO_CPUS(&buffer[bi]);
465969b5a878SDan McDonald 	}
466069b5a878SDan McDonald 
4661*48ed61a7SRobert Mustacchi rel_out:
4662*48ed61a7SRobert Mustacchi 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
4663*48ed61a7SRobert Mustacchi 
4664*48ed61a7SRobert Mustacchi 	return status;
466569b5a878SDan McDonald }
466669b5a878SDan McDonald 
466769b5a878SDan McDonald /**
466869b5a878SDan McDonald  *  ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware
466969b5a878SDan McDonald  *  @hw: pointer to the HW structure
467069b5a878SDan McDonald  *  @maj: driver version major number
467169b5a878SDan McDonald  *  @min: driver version minor number
467269b5a878SDan McDonald  *  @build: driver version build number
467369b5a878SDan McDonald  *  @sub: driver version sub build number
4674*48ed61a7SRobert Mustacchi  *  @len: unused
4675*48ed61a7SRobert Mustacchi  *  @driver_ver: unused
467669b5a878SDan McDonald  *
467769b5a878SDan McDonald  *  Sends driver version number to firmware through the manageability
467869b5a878SDan McDonald  *  block.  On success return IXGBE_SUCCESS
467969b5a878SDan McDonald  *  else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
468069b5a878SDan McDonald  *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
468169b5a878SDan McDonald  **/
ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw * hw,u8 maj,u8 min,u8 build,u8 sub,u16 len,const char * driver_ver)468269b5a878SDan McDonald s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
4683*48ed61a7SRobert Mustacchi 				 u8 build, u8 sub, u16 len,
4684*48ed61a7SRobert Mustacchi 				 const char *driver_ver)
468569b5a878SDan McDonald {
468669b5a878SDan McDonald 	struct ixgbe_hic_drv_info fw_cmd;
468769b5a878SDan McDonald 	int i;
468869b5a878SDan McDonald 	s32 ret_val = IXGBE_SUCCESS;
468969b5a878SDan McDonald 
469069b5a878SDan McDonald 	DEBUGFUNC("ixgbe_set_fw_drv_ver_generic");
4691*48ed61a7SRobert Mustacchi 	UNREFERENCED_2PARAMETER(len, driver_ver);
469269b5a878SDan McDonald 
469369b5a878SDan McDonald 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
469469b5a878SDan McDonald 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
469569b5a878SDan McDonald 	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
469669b5a878SDan McDonald 	fw_cmd.port_num = (u8)hw->bus.func;
469769b5a878SDan McDonald 	fw_cmd.ver_maj = maj;
469869b5a878SDan McDonald 	fw_cmd.ver_min = min;
469969b5a878SDan McDonald 	fw_cmd.ver_build = build;
470069b5a878SDan McDonald 	fw_cmd.ver_sub = sub;
470169b5a878SDan McDonald 	fw_cmd.hdr.checksum = 0;
470269b5a878SDan McDonald 	fw_cmd.pad = 0;
470369b5a878SDan McDonald 	fw_cmd.pad2 = 0;
4704*48ed61a7SRobert Mustacchi 	fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
4705*48ed61a7SRobert Mustacchi 				(FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
470669b5a878SDan McDonald 
470769b5a878SDan McDonald 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
470869b5a878SDan McDonald 		ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
4709dc0cb1cdSDale Ghent 						       sizeof(fw_cmd),
4710dc0cb1cdSDale Ghent 						       IXGBE_HI_COMMAND_TIMEOUT,
4711dc0cb1cdSDale Ghent 						       TRUE);
471269b5a878SDan McDonald 		if (ret_val != IXGBE_SUCCESS)
471369b5a878SDan McDonald 			continue;
471469b5a878SDan McDonald 
471569b5a878SDan McDonald 		if (fw_cmd.hdr.cmd_or_resp.ret_status ==
471669b5a878SDan McDonald 		    FW_CEM_RESP_STATUS_SUCCESS)
471769b5a878SDan McDonald 			ret_val = IXGBE_SUCCESS;
471869b5a878SDan McDonald 		else
471969b5a878SDan McDonald 			ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
472069b5a878SDan McDonald 
472169b5a878SDan McDonald 		break;
472269b5a878SDan McDonald 	}
472369b5a878SDan McDonald 
472469b5a878SDan McDonald 	return ret_val;
472569b5a878SDan McDonald }
472669b5a878SDan McDonald 
472769b5a878SDan McDonald /**
472869b5a878SDan McDonald  * ixgbe_set_rxpba_generic - Initialize Rx packet buffer
472969b5a878SDan McDonald  * @hw: pointer to hardware structure
473069b5a878SDan McDonald  * @num_pb: number of packet buffers to allocate
473169b5a878SDan McDonald  * @headroom: reserve n KB of headroom
473269b5a878SDan McDonald  * @strategy: packet buffer allocation strategy
473369b5a878SDan McDonald  **/
ixgbe_set_rxpba_generic(struct ixgbe_hw * hw,int num_pb,u32 headroom,int strategy)473469b5a878SDan McDonald void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom,
473569b5a878SDan McDonald 			     int strategy)
473669b5a878SDan McDonald {
473769b5a878SDan McDonald 	u32 pbsize = hw->mac.rx_pb_size;
473869b5a878SDan McDonald 	int i = 0;
473969b5a878SDan McDonald 	u32 rxpktsize, txpktsize, txpbthresh;
474069b5a878SDan McDonald 
474169b5a878SDan McDonald 	/* Reserve headroom */
474269b5a878SDan McDonald 	pbsize -= headroom;
474369b5a878SDan McDonald 
474469b5a878SDan McDonald 	if (!num_pb)
474569b5a878SDan McDonald 		num_pb = 1;
474669b5a878SDan McDonald 
474769b5a878SDan McDonald 	/* Divide remaining packet buffer space amongst the number of packet
474869b5a878SDan McDonald 	 * buffers requested using supplied strategy.
474969b5a878SDan McDonald 	 */
475069b5a878SDan McDonald 	switch (strategy) {
475169b5a878SDan McDonald 	case PBA_STRATEGY_WEIGHTED:
475269b5a878SDan McDonald 		/* ixgbe_dcb_pba_80_48 strategy weight first half of packet
475369b5a878SDan McDonald 		 * buffer with 5/8 of the packet buffer space.
475469b5a878SDan McDonald 		 */
475569b5a878SDan McDonald 		rxpktsize = (pbsize * 5) / (num_pb * 4);
475669b5a878SDan McDonald 		pbsize -= rxpktsize * (num_pb / 2);
475769b5a878SDan McDonald 		rxpktsize <<= IXGBE_RXPBSIZE_SHIFT;
475869b5a878SDan McDonald 		for (; i < (num_pb / 2); i++)
475969b5a878SDan McDonald 			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
4760*48ed61a7SRobert Mustacchi 		/* configure remaining packet buffers */
4761e5c421abSToomas Soome 		/* FALLTHROUGH */
476269b5a878SDan McDonald 	case PBA_STRATEGY_EQUAL:
476369b5a878SDan McDonald 		rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT;
476469b5a878SDan McDonald 		for (; i < num_pb; i++)
476569b5a878SDan McDonald 			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
476669b5a878SDan McDonald 		break;
476769b5a878SDan McDonald 	default:
476869b5a878SDan McDonald 		break;
476969b5a878SDan McDonald 	}
477069b5a878SDan McDonald 
477169b5a878SDan McDonald 	/* Only support an equally distributed Tx packet buffer strategy. */
477269b5a878SDan McDonald 	txpktsize = IXGBE_TXPBSIZE_MAX / num_pb;
477369b5a878SDan McDonald 	txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
477469b5a878SDan McDonald 	for (i = 0; i < num_pb; i++) {
477569b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
477669b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
477769b5a878SDan McDonald 	}
477869b5a878SDan McDonald 
477969b5a878SDan McDonald 	/* Clear unused TCs, if any, to zero buffer size*/
478069b5a878SDan McDonald 	for (; i < IXGBE_MAX_PB; i++) {
478169b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
478269b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
478369b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
478469b5a878SDan McDonald 	}
478569b5a878SDan McDonald }
478669b5a878SDan McDonald 
478769b5a878SDan McDonald /**
478869b5a878SDan McDonald  * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo
478969b5a878SDan McDonald  * @hw: pointer to the hardware structure
479069b5a878SDan McDonald  *
479169b5a878SDan McDonald  * The 82599 and x540 MACs can experience issues if TX work is still pending
479269b5a878SDan McDonald  * when a reset occurs.  This function prevents this by flushing the PCIe
479369b5a878SDan McDonald  * buffers on the system.
479469b5a878SDan McDonald  **/
ixgbe_clear_tx_pending(struct ixgbe_hw * hw)479569b5a878SDan McDonald void ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
479669b5a878SDan McDonald {
4797dc0cb1cdSDale Ghent 	u32 gcr_ext, hlreg0, i, poll;
4798dc0cb1cdSDale Ghent 	u16 value;
479969b5a878SDan McDonald 
480069b5a878SDan McDonald 	/*
480169b5a878SDan McDonald 	 * If double reset is not requested then all transactions should
480269b5a878SDan McDonald 	 * already be clear and as such there is no work to do
480369b5a878SDan McDonald 	 */
480469b5a878SDan McDonald 	if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED))
480569b5a878SDan McDonald 		return;
480669b5a878SDan McDonald 
480769b5a878SDan McDonald 	/*
480869b5a878SDan McDonald 	 * Set loopback enable to prevent any transmits from being sent
480969b5a878SDan McDonald 	 * should the link come up.  This assumes that the RXCTRL.RXEN bit
481069b5a878SDan McDonald 	 * has already been cleared.
481169b5a878SDan McDonald 	 */
481269b5a878SDan McDonald 	hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
481369b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK);
481469b5a878SDan McDonald 
4815dc0cb1cdSDale Ghent 	/* Wait for a last completion before clearing buffers */
4816dc0cb1cdSDale Ghent 	IXGBE_WRITE_FLUSH(hw);
4817dc0cb1cdSDale Ghent 	msec_delay(3);
4818dc0cb1cdSDale Ghent 
4819dc0cb1cdSDale Ghent 	/*
4820dc0cb1cdSDale Ghent 	 * Before proceeding, make sure that the PCIe block does not have
4821dc0cb1cdSDale Ghent 	 * transactions pending.
4822dc0cb1cdSDale Ghent 	 */
4823dc0cb1cdSDale Ghent 	poll = ixgbe_pcie_timeout_poll(hw);
4824dc0cb1cdSDale Ghent 	for (i = 0; i < poll; i++) {
4825dc0cb1cdSDale Ghent 		usec_delay(100);
4826dc0cb1cdSDale Ghent 		value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS);
482774b989c3SRobert Mustacchi 		if (IXGBE_REMOVED(hw))
4828dc0cb1cdSDale Ghent 			goto out;
4829dc0cb1cdSDale Ghent 		if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
4830dc0cb1cdSDale Ghent 			goto out;
4831dc0cb1cdSDale Ghent 	}
4832dc0cb1cdSDale Ghent 
4833dc0cb1cdSDale Ghent out:
483469b5a878SDan McDonald 	/* initiate cleaning flow for buffers in the PCIe transaction layer */
483569b5a878SDan McDonald 	gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
483669b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT,
483769b5a878SDan McDonald 			gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR);
483869b5a878SDan McDonald 
483969b5a878SDan McDonald 	/* Flush all writes and allow 20usec for all transactions to clear */
484069b5a878SDan McDonald 	IXGBE_WRITE_FLUSH(hw);
484169b5a878SDan McDonald 	usec_delay(20);
484269b5a878SDan McDonald 
484369b5a878SDan McDonald 	/* restore previous register values */
484469b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
484569b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
484669b5a878SDan McDonald }
484769b5a878SDan McDonald 
4848*48ed61a7SRobert Mustacchi /**
4849*48ed61a7SRobert Mustacchi  *  ixgbe_bypass_rw_generic - Bit bang data into by_pass FW
4850*48ed61a7SRobert Mustacchi  *
4851*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
4852*48ed61a7SRobert Mustacchi  *  @cmd: Command we send to the FW
4853*48ed61a7SRobert Mustacchi  *  @status: The reply from the FW
4854*48ed61a7SRobert Mustacchi  *
4855*48ed61a7SRobert Mustacchi  *  Bit-bangs the cmd to the by_pass FW status points to what is returned.
4856*48ed61a7SRobert Mustacchi  **/
4857*48ed61a7SRobert Mustacchi #define IXGBE_BYPASS_BB_WAIT 1
ixgbe_bypass_rw_generic(struct ixgbe_hw * hw,u32 cmd,u32 * status)4858*48ed61a7SRobert Mustacchi s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status)
4859*48ed61a7SRobert Mustacchi {
4860*48ed61a7SRobert Mustacchi 	int i;
4861*48ed61a7SRobert Mustacchi 	u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo;
4862*48ed61a7SRobert Mustacchi 	u32 esdp;
4863*48ed61a7SRobert Mustacchi 
4864*48ed61a7SRobert Mustacchi 	if (!status)
4865*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_PARAM;
4866*48ed61a7SRobert Mustacchi 
4867*48ed61a7SRobert Mustacchi 	*status = 0;
4868*48ed61a7SRobert Mustacchi 
4869*48ed61a7SRobert Mustacchi 	/* SDP vary by MAC type */
4870*48ed61a7SRobert Mustacchi 	switch (hw->mac.type) {
4871*48ed61a7SRobert Mustacchi 	case ixgbe_mac_82599EB:
4872*48ed61a7SRobert Mustacchi 		sck = IXGBE_ESDP_SDP7;
4873*48ed61a7SRobert Mustacchi 		sdi = IXGBE_ESDP_SDP0;
4874*48ed61a7SRobert Mustacchi 		sdo = IXGBE_ESDP_SDP6;
4875*48ed61a7SRobert Mustacchi 		dir_sck = IXGBE_ESDP_SDP7_DIR;
4876*48ed61a7SRobert Mustacchi 		dir_sdi = IXGBE_ESDP_SDP0_DIR;
4877*48ed61a7SRobert Mustacchi 		dir_sdo = IXGBE_ESDP_SDP6_DIR;
4878*48ed61a7SRobert Mustacchi 		break;
4879*48ed61a7SRobert Mustacchi 	case ixgbe_mac_X540:
4880*48ed61a7SRobert Mustacchi 		sck = IXGBE_ESDP_SDP2;
4881*48ed61a7SRobert Mustacchi 		sdi = IXGBE_ESDP_SDP0;
4882*48ed61a7SRobert Mustacchi 		sdo = IXGBE_ESDP_SDP1;
4883*48ed61a7SRobert Mustacchi 		dir_sck = IXGBE_ESDP_SDP2_DIR;
4884*48ed61a7SRobert Mustacchi 		dir_sdi = IXGBE_ESDP_SDP0_DIR;
4885*48ed61a7SRobert Mustacchi 		dir_sdo = IXGBE_ESDP_SDP1_DIR;
4886*48ed61a7SRobert Mustacchi 		break;
4887*48ed61a7SRobert Mustacchi 	default:
4888*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_DEVICE_NOT_SUPPORTED;
4889*48ed61a7SRobert Mustacchi 	}
4890*48ed61a7SRobert Mustacchi 
4891*48ed61a7SRobert Mustacchi 	/* Set SDP pins direction */
4892*48ed61a7SRobert Mustacchi 	esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
4893*48ed61a7SRobert Mustacchi 	esdp |= dir_sck;	/* SCK as output */
4894*48ed61a7SRobert Mustacchi 	esdp |= dir_sdi;	/* SDI as output */
4895*48ed61a7SRobert Mustacchi 	esdp &= ~dir_sdo;	/* SDO as input */
4896*48ed61a7SRobert Mustacchi 	esdp |= sck;
4897*48ed61a7SRobert Mustacchi 	esdp |= sdi;
4898*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4899*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_FLUSH(hw);
4900*48ed61a7SRobert Mustacchi 	msec_delay(IXGBE_BYPASS_BB_WAIT);
4901*48ed61a7SRobert Mustacchi 
4902*48ed61a7SRobert Mustacchi 	/* Generate start condition */
4903*48ed61a7SRobert Mustacchi 	esdp &= ~sdi;
4904*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4905*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_FLUSH(hw);
4906*48ed61a7SRobert Mustacchi 	msec_delay(IXGBE_BYPASS_BB_WAIT);
4907*48ed61a7SRobert Mustacchi 
4908*48ed61a7SRobert Mustacchi 	esdp &= ~sck;
4909*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4910*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_FLUSH(hw);
4911*48ed61a7SRobert Mustacchi 	msec_delay(IXGBE_BYPASS_BB_WAIT);
4912*48ed61a7SRobert Mustacchi 
4913*48ed61a7SRobert Mustacchi 	/* Clock out the new control word and clock in the status */
4914*48ed61a7SRobert Mustacchi 	for (i = 0; i < 32; i++) {
4915*48ed61a7SRobert Mustacchi 		if ((cmd >> (31 - i)) & 0x01) {
4916*48ed61a7SRobert Mustacchi 			esdp |= sdi;
4917*48ed61a7SRobert Mustacchi 			IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4918*48ed61a7SRobert Mustacchi 		} else {
4919*48ed61a7SRobert Mustacchi 			esdp &= ~sdi;
4920*48ed61a7SRobert Mustacchi 			IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4921*48ed61a7SRobert Mustacchi 		}
4922*48ed61a7SRobert Mustacchi 		IXGBE_WRITE_FLUSH(hw);
4923*48ed61a7SRobert Mustacchi 		msec_delay(IXGBE_BYPASS_BB_WAIT);
4924*48ed61a7SRobert Mustacchi 
4925*48ed61a7SRobert Mustacchi 		esdp |= sck;
4926*48ed61a7SRobert Mustacchi 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4927*48ed61a7SRobert Mustacchi 		IXGBE_WRITE_FLUSH(hw);
4928*48ed61a7SRobert Mustacchi 		msec_delay(IXGBE_BYPASS_BB_WAIT);
4929*48ed61a7SRobert Mustacchi 
4930*48ed61a7SRobert Mustacchi 		esdp &= ~sck;
4931*48ed61a7SRobert Mustacchi 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4932*48ed61a7SRobert Mustacchi 		IXGBE_WRITE_FLUSH(hw);
4933*48ed61a7SRobert Mustacchi 		msec_delay(IXGBE_BYPASS_BB_WAIT);
4934*48ed61a7SRobert Mustacchi 
4935*48ed61a7SRobert Mustacchi 		esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
4936*48ed61a7SRobert Mustacchi 		if (esdp & sdo)
4937*48ed61a7SRobert Mustacchi 			*status = (*status << 1) | 0x01;
4938*48ed61a7SRobert Mustacchi 		else
4939*48ed61a7SRobert Mustacchi 			*status = (*status << 1) | 0x00;
4940*48ed61a7SRobert Mustacchi 		msec_delay(IXGBE_BYPASS_BB_WAIT);
4941*48ed61a7SRobert Mustacchi 	}
4942*48ed61a7SRobert Mustacchi 
4943*48ed61a7SRobert Mustacchi 	/* stop condition */
4944*48ed61a7SRobert Mustacchi 	esdp |= sck;
4945*48ed61a7SRobert Mustacchi 	esdp &= ~sdi;
4946*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4947*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_FLUSH(hw);
4948*48ed61a7SRobert Mustacchi 	msec_delay(IXGBE_BYPASS_BB_WAIT);
4949*48ed61a7SRobert Mustacchi 
4950*48ed61a7SRobert Mustacchi 	esdp |= sdi;
4951*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
4952*48ed61a7SRobert Mustacchi 	IXGBE_WRITE_FLUSH(hw);
4953*48ed61a7SRobert Mustacchi 
4954*48ed61a7SRobert Mustacchi 	/* set the page bits to match the cmd that the status it belongs to */
4955*48ed61a7SRobert Mustacchi 	*status = (*status & 0x3fffffff) | (cmd & 0xc0000000);
4956*48ed61a7SRobert Mustacchi 
4957*48ed61a7SRobert Mustacchi 	return IXGBE_SUCCESS;
4958*48ed61a7SRobert Mustacchi }
4959*48ed61a7SRobert Mustacchi 
4960*48ed61a7SRobert Mustacchi /**
4961*48ed61a7SRobert Mustacchi  * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang.
4962*48ed61a7SRobert Mustacchi  *
4963*48ed61a7SRobert Mustacchi  * If we send a write we can't be sure it took until we can read back
4964*48ed61a7SRobert Mustacchi  * that same register.  It can be a problem as some of the feilds may
4965*48ed61a7SRobert Mustacchi  * for valid reasons change inbetween the time wrote the register and
4966*48ed61a7SRobert Mustacchi  * we read it again to verify.  So this function check everything we
4967*48ed61a7SRobert Mustacchi  * can check and then assumes it worked.
4968*48ed61a7SRobert Mustacchi  *
4969*48ed61a7SRobert Mustacchi  * @u32 in_reg - The register cmd for the bit-bang read.
4970*48ed61a7SRobert Mustacchi  * @u32 out_reg - The register returned from a bit-bang read.
4971*48ed61a7SRobert Mustacchi  **/
ixgbe_bypass_valid_rd_generic(u32 in_reg,u32 out_reg)4972*48ed61a7SRobert Mustacchi bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg)
4973*48ed61a7SRobert Mustacchi {
4974*48ed61a7SRobert Mustacchi 	u32 mask;
4975*48ed61a7SRobert Mustacchi 
4976*48ed61a7SRobert Mustacchi 	/* Page must match for all control pages */
4977*48ed61a7SRobert Mustacchi 	if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M))
4978*48ed61a7SRobert Mustacchi 		return FALSE;
4979*48ed61a7SRobert Mustacchi 
4980*48ed61a7SRobert Mustacchi 	switch (in_reg & BYPASS_PAGE_M) {
4981*48ed61a7SRobert Mustacchi 	case BYPASS_PAGE_CTL0:
4982*48ed61a7SRobert Mustacchi 		/* All the following can't change since the last write
4983*48ed61a7SRobert Mustacchi 		 *  - All the event actions
4984*48ed61a7SRobert Mustacchi 		 *  - The timeout value
4985*48ed61a7SRobert Mustacchi 		 */
4986*48ed61a7SRobert Mustacchi 		mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M |
4987*48ed61a7SRobert Mustacchi 		       BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M |
4988*48ed61a7SRobert Mustacchi 		       BYPASS_WDTIMEOUT_M |
4989*48ed61a7SRobert Mustacchi 		       BYPASS_WDT_VALUE_M;
4990*48ed61a7SRobert Mustacchi 		if ((out_reg & mask) != (in_reg & mask))
4991*48ed61a7SRobert Mustacchi 			return FALSE;
4992*48ed61a7SRobert Mustacchi 
4993*48ed61a7SRobert Mustacchi 		/* 0x0 is never a valid value for bypass status */
4994*48ed61a7SRobert Mustacchi 		if (!(out_reg & BYPASS_STATUS_OFF_M))
4995*48ed61a7SRobert Mustacchi 			return FALSE;
4996*48ed61a7SRobert Mustacchi 		break;
4997*48ed61a7SRobert Mustacchi 	case BYPASS_PAGE_CTL1:
4998*48ed61a7SRobert Mustacchi 		/* All the following can't change since the last write
4999*48ed61a7SRobert Mustacchi 		 *  - time valid bit
5000*48ed61a7SRobert Mustacchi 		 *  - time we last sent
5001*48ed61a7SRobert Mustacchi 		 */
5002*48ed61a7SRobert Mustacchi 		mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M;
5003*48ed61a7SRobert Mustacchi 		if ((out_reg & mask) != (in_reg & mask))
5004*48ed61a7SRobert Mustacchi 			return FALSE;
5005*48ed61a7SRobert Mustacchi 		break;
5006*48ed61a7SRobert Mustacchi 	case BYPASS_PAGE_CTL2:
5007*48ed61a7SRobert Mustacchi 		/* All we can check in this page is control number
5008*48ed61a7SRobert Mustacchi 		 * which is already done above.
5009*48ed61a7SRobert Mustacchi 		 */
5010*48ed61a7SRobert Mustacchi 		break;
5011*48ed61a7SRobert Mustacchi 	}
5012*48ed61a7SRobert Mustacchi 
5013*48ed61a7SRobert Mustacchi 	/* We are as sure as we can be return TRUE */
5014*48ed61a7SRobert Mustacchi 	return TRUE;
5015*48ed61a7SRobert Mustacchi }
5016*48ed61a7SRobert Mustacchi 
5017*48ed61a7SRobert Mustacchi /**
5018*48ed61a7SRobert Mustacchi  *  ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter.
5019*48ed61a7SRobert Mustacchi  *
5020*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
5021*48ed61a7SRobert Mustacchi  *  @cmd: The control word we are setting.
5022*48ed61a7SRobert Mustacchi  *  @event: The event we are setting in the FW.  This also happens to
5023*48ed61a7SRobert Mustacchi  *	    be the mask for the event we are setting (handy)
5024*48ed61a7SRobert Mustacchi  *  @action: The action we set the event to in the FW. This is in a
5025*48ed61a7SRobert Mustacchi  *	     bit field that happens to be what we want to put in
5026*48ed61a7SRobert Mustacchi  *	     the event spot (also handy)
5027*48ed61a7SRobert Mustacchi  **/
ixgbe_bypass_set_generic(struct ixgbe_hw * hw,u32 ctrl,u32 event,u32 action)5028*48ed61a7SRobert Mustacchi s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
5029*48ed61a7SRobert Mustacchi 			     u32 action)
5030*48ed61a7SRobert Mustacchi {
5031*48ed61a7SRobert Mustacchi 	u32 by_ctl = 0;
5032*48ed61a7SRobert Mustacchi 	u32 cmd, verify;
5033*48ed61a7SRobert Mustacchi 	u32 count = 0;
5034*48ed61a7SRobert Mustacchi 
5035*48ed61a7SRobert Mustacchi 	/* Get current values */
5036*48ed61a7SRobert Mustacchi 	cmd = ctrl;	/* just reading only need control number */
5037*48ed61a7SRobert Mustacchi 	if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
5038*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_INVALID_ARGUMENT;
5039*48ed61a7SRobert Mustacchi 
5040*48ed61a7SRobert Mustacchi 	/* Set to new action */
5041*48ed61a7SRobert Mustacchi 	cmd = (by_ctl & ~event) | BYPASS_WE | action;
5042*48ed61a7SRobert Mustacchi 	if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
5043*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_INVALID_ARGUMENT;
5044*48ed61a7SRobert Mustacchi 
5045*48ed61a7SRobert Mustacchi 	/* Page 0 force a FW eeprom write which is slow so verify */
5046*48ed61a7SRobert Mustacchi 	if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) {
5047*48ed61a7SRobert Mustacchi 		verify = BYPASS_PAGE_CTL0;
5048*48ed61a7SRobert Mustacchi 		do {
5049*48ed61a7SRobert Mustacchi 			if (count++ > 5)
5050*48ed61a7SRobert Mustacchi 				return IXGBE_BYPASS_FW_WRITE_FAILURE;
5051*48ed61a7SRobert Mustacchi 
5052*48ed61a7SRobert Mustacchi 			if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl))
5053*48ed61a7SRobert Mustacchi 				return IXGBE_ERR_INVALID_ARGUMENT;
5054*48ed61a7SRobert Mustacchi 		} while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl));
5055*48ed61a7SRobert Mustacchi 	} else {
5056*48ed61a7SRobert Mustacchi 		/* We have give the FW time for the write to stick */
5057*48ed61a7SRobert Mustacchi 		msec_delay(100);
5058*48ed61a7SRobert Mustacchi 	}
5059*48ed61a7SRobert Mustacchi 
5060*48ed61a7SRobert Mustacchi 	return IXGBE_SUCCESS;
5061*48ed61a7SRobert Mustacchi }
5062*48ed61a7SRobert Mustacchi 
5063*48ed61a7SRobert Mustacchi /**
5064*48ed61a7SRobert Mustacchi  *  ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres.
5065*48ed61a7SRobert Mustacchi  *
5066*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
5067*48ed61a7SRobert Mustacchi  *  @addr: The bypass eeprom address to read.
5068*48ed61a7SRobert Mustacchi  *  @value: The 8b of data at the address above.
5069*48ed61a7SRobert Mustacchi  **/
ixgbe_bypass_rd_eep_generic(struct ixgbe_hw * hw,u32 addr,u8 * value)5070*48ed61a7SRobert Mustacchi s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value)
5071*48ed61a7SRobert Mustacchi {
5072*48ed61a7SRobert Mustacchi 	u32 cmd;
5073*48ed61a7SRobert Mustacchi 	u32 status;
5074*48ed61a7SRobert Mustacchi 
5075*48ed61a7SRobert Mustacchi 
5076*48ed61a7SRobert Mustacchi 	/* send the request */
5077*48ed61a7SRobert Mustacchi 	cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
5078*48ed61a7SRobert Mustacchi 	cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
5079*48ed61a7SRobert Mustacchi 	if (ixgbe_bypass_rw_generic(hw, cmd, &status))
5080*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_INVALID_ARGUMENT;
5081*48ed61a7SRobert Mustacchi 
5082*48ed61a7SRobert Mustacchi 	/* We have give the FW time for the write to stick */
5083*48ed61a7SRobert Mustacchi 	msec_delay(100);
5084*48ed61a7SRobert Mustacchi 
5085*48ed61a7SRobert Mustacchi 	/* now read the results */
5086*48ed61a7SRobert Mustacchi 	cmd &= ~BYPASS_WE;
5087*48ed61a7SRobert Mustacchi 	if (ixgbe_bypass_rw_generic(hw, cmd, &status))
5088*48ed61a7SRobert Mustacchi 		return IXGBE_ERR_INVALID_ARGUMENT;
5089*48ed61a7SRobert Mustacchi 
5090*48ed61a7SRobert Mustacchi 	*value = status & BYPASS_CTL2_DATA_M;
5091*48ed61a7SRobert Mustacchi 
5092*48ed61a7SRobert Mustacchi 	return IXGBE_SUCCESS;
5093*48ed61a7SRobert Mustacchi }
5094*48ed61a7SRobert Mustacchi 
5095*48ed61a7SRobert Mustacchi /**
5096*48ed61a7SRobert Mustacchi  *  ixgbe_get_orom_version - Return option ROM from EEPROM
5097*48ed61a7SRobert Mustacchi  *
5098*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
5099*48ed61a7SRobert Mustacchi  *  @nvm_ver: pointer to output structure
5100*48ed61a7SRobert Mustacchi  *
5101*48ed61a7SRobert Mustacchi  *  if valid option ROM version, nvm_ver->or_valid set to TRUE
5102*48ed61a7SRobert Mustacchi  *  else nvm_ver->or_valid is FALSE.
5103*48ed61a7SRobert Mustacchi  **/
ixgbe_get_orom_version(struct ixgbe_hw * hw,struct ixgbe_nvm_version * nvm_ver)5104*48ed61a7SRobert Mustacchi void ixgbe_get_orom_version(struct ixgbe_hw *hw,
5105*48ed61a7SRobert Mustacchi 			    struct ixgbe_nvm_version *nvm_ver)
5106*48ed61a7SRobert Mustacchi {
5107*48ed61a7SRobert Mustacchi 	u16 offset, eeprom_cfg_blkh, eeprom_cfg_blkl;
5108*48ed61a7SRobert Mustacchi 
5109*48ed61a7SRobert Mustacchi 	nvm_ver->or_valid = FALSE;
5110*48ed61a7SRobert Mustacchi 	/* Option Rom may or may not be present.  Start with pointer */
5111*48ed61a7SRobert Mustacchi 	hw->eeprom.ops.read(hw, NVM_OROM_OFFSET, &offset);
5112*48ed61a7SRobert Mustacchi 
5113*48ed61a7SRobert Mustacchi 	/* make sure offset is valid */
5114*48ed61a7SRobert Mustacchi 	if ((offset == 0x0) || (offset == NVM_INVALID_PTR))
5115*48ed61a7SRobert Mustacchi 		return;
5116*48ed61a7SRobert Mustacchi 
5117*48ed61a7SRobert Mustacchi 	hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_HI, &eeprom_cfg_blkh);
5118*48ed61a7SRobert Mustacchi 	hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_LOW, &eeprom_cfg_blkl);
5119*48ed61a7SRobert Mustacchi 
5120*48ed61a7SRobert Mustacchi 	/* option rom exists and is valid */
5121*48ed61a7SRobert Mustacchi 	if ((eeprom_cfg_blkl | eeprom_cfg_blkh) == 0x0 ||
5122*48ed61a7SRobert Mustacchi 	    eeprom_cfg_blkl == NVM_VER_INVALID ||
5123*48ed61a7SRobert Mustacchi 	    eeprom_cfg_blkh == NVM_VER_INVALID)
5124*48ed61a7SRobert Mustacchi 		return;
5125*48ed61a7SRobert Mustacchi 
5126*48ed61a7SRobert Mustacchi 	nvm_ver->or_valid = TRUE;
5127*48ed61a7SRobert Mustacchi 	nvm_ver->or_major = eeprom_cfg_blkl >> NVM_OROM_SHIFT;
5128*48ed61a7SRobert Mustacchi 	nvm_ver->or_build = (eeprom_cfg_blkl << NVM_OROM_SHIFT) |
5129*48ed61a7SRobert Mustacchi 			    (eeprom_cfg_blkh >> NVM_OROM_SHIFT);
5130*48ed61a7SRobert Mustacchi 	nvm_ver->or_patch = eeprom_cfg_blkh & NVM_OROM_PATCH_MASK;
5131*48ed61a7SRobert Mustacchi }
5132*48ed61a7SRobert Mustacchi 
5133*48ed61a7SRobert Mustacchi /**
5134*48ed61a7SRobert Mustacchi  *  ixgbe_get_oem_prod_version - Return OEM Product version
5135*48ed61a7SRobert Mustacchi  *
5136*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
5137*48ed61a7SRobert Mustacchi  *  @nvm_ver: pointer to output structure
5138*48ed61a7SRobert Mustacchi  *
5139*48ed61a7SRobert Mustacchi  *  if valid OEM product version, nvm_ver->oem_valid set to TRUE
5140*48ed61a7SRobert Mustacchi  *  else nvm_ver->oem_valid is FALSE.
5141*48ed61a7SRobert Mustacchi  **/
ixgbe_get_oem_prod_version(struct ixgbe_hw * hw,struct ixgbe_nvm_version * nvm_ver)5142*48ed61a7SRobert Mustacchi void ixgbe_get_oem_prod_version(struct ixgbe_hw *hw,
5143*48ed61a7SRobert Mustacchi 				struct ixgbe_nvm_version *nvm_ver)
5144*48ed61a7SRobert Mustacchi {
5145*48ed61a7SRobert Mustacchi 	u16 rel_num, prod_ver, mod_len, cap, offset;
5146*48ed61a7SRobert Mustacchi 
5147*48ed61a7SRobert Mustacchi 	nvm_ver->oem_valid = FALSE;
5148*48ed61a7SRobert Mustacchi 	hw->eeprom.ops.read(hw, NVM_OEM_PROD_VER_PTR, &offset);
5149*48ed61a7SRobert Mustacchi 
5150*48ed61a7SRobert Mustacchi 	/* Return is offset to OEM Product Version block is invalid */
5151*48ed61a7SRobert Mustacchi 	if (offset == 0x0 || offset == NVM_INVALID_PTR)
5152*48ed61a7SRobert Mustacchi 		return;
5153*48ed61a7SRobert Mustacchi 
5154*48ed61a7SRobert Mustacchi 	/* Read product version block */
5155*48ed61a7SRobert Mustacchi 	hw->eeprom.ops.read(hw, offset, &mod_len);
5156*48ed61a7SRobert Mustacchi 	hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_CAP_OFF, &cap);
5157*48ed61a7SRobert Mustacchi 
5158*48ed61a7SRobert Mustacchi 	/* Return if OEM product version block is invalid */
5159*48ed61a7SRobert Mustacchi 	if (mod_len != NVM_OEM_PROD_VER_MOD_LEN ||
5160*48ed61a7SRobert Mustacchi 	    (cap & NVM_OEM_PROD_VER_CAP_MASK) != 0x0)
5161*48ed61a7SRobert Mustacchi 		return;
5162*48ed61a7SRobert Mustacchi 
5163*48ed61a7SRobert Mustacchi 	hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_L, &prod_ver);
5164*48ed61a7SRobert Mustacchi 	hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_H, &rel_num);
5165*48ed61a7SRobert Mustacchi 
5166*48ed61a7SRobert Mustacchi 	/* Return if version is invalid */
5167*48ed61a7SRobert Mustacchi 	if ((rel_num | prod_ver) == 0x0 ||
5168*48ed61a7SRobert Mustacchi 	    rel_num == NVM_VER_INVALID || prod_ver == NVM_VER_INVALID)
5169*48ed61a7SRobert Mustacchi 		return;
5170*48ed61a7SRobert Mustacchi 
5171*48ed61a7SRobert Mustacchi 	nvm_ver->oem_major = prod_ver >> NVM_VER_SHIFT;
5172*48ed61a7SRobert Mustacchi 	nvm_ver->oem_minor = prod_ver & NVM_VER_MASK;
5173*48ed61a7SRobert Mustacchi 	nvm_ver->oem_release = rel_num;
5174*48ed61a7SRobert Mustacchi 	nvm_ver->oem_valid = TRUE;
5175*48ed61a7SRobert Mustacchi }
5176*48ed61a7SRobert Mustacchi 
5177*48ed61a7SRobert Mustacchi /**
5178*48ed61a7SRobert Mustacchi  *  ixgbe_get_etk_id - Return Etrack ID from EEPROM
5179*48ed61a7SRobert Mustacchi  *
5180*48ed61a7SRobert Mustacchi  *  @hw: pointer to hardware structure
5181*48ed61a7SRobert Mustacchi  *  @nvm_ver: pointer to output structure
5182*48ed61a7SRobert Mustacchi  *
5183*48ed61a7SRobert Mustacchi  *  word read errors will return 0xFFFF
5184*48ed61a7SRobert Mustacchi  **/
ixgbe_get_etk_id(struct ixgbe_hw * hw,struct ixgbe_nvm_version * nvm_ver)5185*48ed61a7SRobert Mustacchi void ixgbe_get_etk_id(struct ixgbe_hw *hw, struct ixgbe_nvm_version *nvm_ver)
5186*48ed61a7SRobert Mustacchi {
5187*48ed61a7SRobert Mustacchi 	u16 etk_id_l, etk_id_h;
5188*48ed61a7SRobert Mustacchi 
5189*48ed61a7SRobert Mustacchi 	if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_LOW, &etk_id_l))
5190*48ed61a7SRobert Mustacchi 		etk_id_l = NVM_VER_INVALID;
5191*48ed61a7SRobert Mustacchi 	if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_HI, &etk_id_h))
5192*48ed61a7SRobert Mustacchi 		etk_id_h = NVM_VER_INVALID;
5193*48ed61a7SRobert Mustacchi 
5194*48ed61a7SRobert Mustacchi 	/* The word order for the version format is determined by high order
5195*48ed61a7SRobert Mustacchi 	 * word bit 15.
5196*48ed61a7SRobert Mustacchi 	 */
5197*48ed61a7SRobert Mustacchi 	if ((etk_id_h & NVM_ETK_VALID) == 0) {
5198*48ed61a7SRobert Mustacchi 		nvm_ver->etk_id = etk_id_h;
5199*48ed61a7SRobert Mustacchi 		nvm_ver->etk_id |= (etk_id_l << NVM_ETK_SHIFT);
5200*48ed61a7SRobert Mustacchi 	} else {
5201*48ed61a7SRobert Mustacchi 		nvm_ver->etk_id = etk_id_l;
5202*48ed61a7SRobert Mustacchi 		nvm_ver->etk_id |= (etk_id_h << NVM_ETK_SHIFT);
5203*48ed61a7SRobert Mustacchi 	}
5204*48ed61a7SRobert Mustacchi }
5205*48ed61a7SRobert Mustacchi 
5206dc0cb1cdSDale Ghent 
5207dc0cb1cdSDale Ghent /**
5208dc0cb1cdSDale Ghent  * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg
5209dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
5210dc0cb1cdSDale Ghent  * @map: pointer to u8 arr for returning map
5211dc0cb1cdSDale Ghent  *
5212dc0cb1cdSDale Ghent  * Read the rtrup2tc HW register and resolve its content into map
5213dc0cb1cdSDale Ghent  **/
ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw * hw,u8 * map)5214dc0cb1cdSDale Ghent void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map)
5215dc0cb1cdSDale Ghent {
5216dc0cb1cdSDale Ghent 	u32 reg, i;
5217dc0cb1cdSDale Ghent 
5218dc0cb1cdSDale Ghent 	reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC);
5219dc0cb1cdSDale Ghent 	for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++)
5220dc0cb1cdSDale Ghent 		map[i] = IXGBE_RTRUP2TC_UP_MASK &
5221dc0cb1cdSDale Ghent 			(reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT));
5222dc0cb1cdSDale Ghent 	return;
5223dc0cb1cdSDale Ghent }
5224dc0cb1cdSDale Ghent 
ixgbe_disable_rx_generic(struct ixgbe_hw * hw)5225dc0cb1cdSDale Ghent void ixgbe_disable_rx_generic(struct ixgbe_hw *hw)
5226dc0cb1cdSDale Ghent {
5227dc0cb1cdSDale Ghent 	u32 pfdtxgswc;
5228dc0cb1cdSDale Ghent 	u32 rxctrl;
5229dc0cb1cdSDale Ghent 
5230dc0cb1cdSDale Ghent 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
5231dc0cb1cdSDale Ghent 	if (rxctrl & IXGBE_RXCTRL_RXEN) {
5232dc0cb1cdSDale Ghent 		if (hw->mac.type != ixgbe_mac_82598EB) {
5233dc0cb1cdSDale Ghent 			pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
5234dc0cb1cdSDale Ghent 			if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
5235dc0cb1cdSDale Ghent 				pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
5236dc0cb1cdSDale Ghent 				IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
5237dc0cb1cdSDale Ghent 				hw->mac.set_lben = TRUE;
5238dc0cb1cdSDale Ghent 			} else {
5239dc0cb1cdSDale Ghent 				hw->mac.set_lben = FALSE;
5240dc0cb1cdSDale Ghent 			}
5241dc0cb1cdSDale Ghent 		}
5242dc0cb1cdSDale Ghent 		rxctrl &= ~IXGBE_RXCTRL_RXEN;
5243dc0cb1cdSDale Ghent 		IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
5244dc0cb1cdSDale Ghent 	}
5245dc0cb1cdSDale Ghent }
5246dc0cb1cdSDale Ghent 
ixgbe_enable_rx_generic(struct ixgbe_hw * hw)5247dc0cb1cdSDale Ghent void ixgbe_enable_rx_generic(struct ixgbe_hw *hw)
5248dc0cb1cdSDale Ghent {
5249dc0cb1cdSDale Ghent 	u32 pfdtxgswc;
5250dc0cb1cdSDale Ghent 	u32 rxctrl;
5251dc0cb1cdSDale Ghent 
5252dc0cb1cdSDale Ghent 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
5253dc0cb1cdSDale Ghent 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN));
5254dc0cb1cdSDale Ghent 
5255dc0cb1cdSDale Ghent 	if (hw->mac.type != ixgbe_mac_82598EB) {
5256dc0cb1cdSDale Ghent 		if (hw->mac.set_lben) {
5257dc0cb1cdSDale Ghent 			pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
5258dc0cb1cdSDale Ghent 			pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN;
5259dc0cb1cdSDale Ghent 			IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
5260dc0cb1cdSDale Ghent 			hw->mac.set_lben = FALSE;
5261dc0cb1cdSDale Ghent 		}
5262dc0cb1cdSDale Ghent 	}
5263dc0cb1cdSDale Ghent }
5264dc0cb1cdSDale Ghent 
5265dc0cb1cdSDale Ghent /**
5266dc0cb1cdSDale Ghent  * ixgbe_mng_present - returns TRUE when management capability is present
5267dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
5268dc0cb1cdSDale Ghent  */
ixgbe_mng_present(struct ixgbe_hw * hw)5269dc0cb1cdSDale Ghent bool ixgbe_mng_present(struct ixgbe_hw *hw)
5270dc0cb1cdSDale Ghent {
5271dc0cb1cdSDale Ghent 	u32 fwsm;
5272dc0cb1cdSDale Ghent 
5273dc0cb1cdSDale Ghent 	if (hw->mac.type < ixgbe_mac_82599EB)
5274dc0cb1cdSDale Ghent 		return FALSE;
5275dc0cb1cdSDale Ghent 
5276dc0cb1cdSDale Ghent 	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
5277*48ed61a7SRobert Mustacchi 
5278*48ed61a7SRobert Mustacchi 	return !!(fwsm & IXGBE_FWSM_FW_MODE_PT);
5279dc0cb1cdSDale Ghent }
5280dc0cb1cdSDale Ghent 
5281dc0cb1cdSDale Ghent /**
5282dc0cb1cdSDale Ghent  * ixgbe_mng_enabled - Is the manageability engine enabled?
5283dc0cb1cdSDale Ghent  * @hw: pointer to hardware structure
5284dc0cb1cdSDale Ghent  *
5285dc0cb1cdSDale Ghent  * Returns TRUE if the manageability engine is enabled.
5286dc0cb1cdSDale Ghent  **/
ixgbe_mng_enabled(struct ixgbe_hw * hw)5287dc0cb1cdSDale Ghent bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
5288dc0cb1cdSDale Ghent {
5289dc0cb1cdSDale Ghent 	u32 fwsm, manc, factps;
5290dc0cb1cdSDale Ghent 
5291dc0cb1cdSDale Ghent 	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
5292dc0cb1cdSDale Ghent 	if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
5293dc0cb1cdSDale Ghent 		return FALSE;
5294dc0cb1cdSDale Ghent 
5295dc0cb1cdSDale Ghent 	manc = IXGBE_READ_REG(hw, IXGBE_MANC);
5296dc0cb1cdSDale Ghent 	if (!(manc & IXGBE_MANC_RCV_TCO_EN))
5297dc0cb1cdSDale Ghent 		return FALSE;
5298dc0cb1cdSDale Ghent 
5299dc0cb1cdSDale Ghent 	if (hw->mac.type <= ixgbe_mac_X540) {
5300dc0cb1cdSDale Ghent 		factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
5301dc0cb1cdSDale Ghent 		if (factps & IXGBE_FACTPS_MNGCG)
5302dc0cb1cdSDale Ghent 			return FALSE;
5303dc0cb1cdSDale Ghent 	}
5304dc0cb1cdSDale Ghent 
5305dc0cb1cdSDale Ghent 	return TRUE;
5306dc0cb1cdSDale Ghent }
5307dc0cb1cdSDale Ghent 
5308dc0cb1cdSDale Ghent /**
5309dc0cb1cdSDale Ghent  *  ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
5310dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
5311dc0cb1cdSDale Ghent  *  @speed: new link speed
5312dc0cb1cdSDale Ghent  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
5313dc0cb1cdSDale Ghent  *
5314dc0cb1cdSDale Ghent  *  Set the link speed in the MAC and/or PHY register and restarts link.
5315dc0cb1cdSDale Ghent  **/
ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)5316dc0cb1cdSDale Ghent s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
5317dc0cb1cdSDale Ghent 					  ixgbe_link_speed speed,
5318dc0cb1cdSDale Ghent 					  bool autoneg_wait_to_complete)
5319dc0cb1cdSDale Ghent {
5320dc0cb1cdSDale Ghent 	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
5321dc0cb1cdSDale Ghent 	ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
5322dc0cb1cdSDale Ghent 	s32 status = IXGBE_SUCCESS;
5323dc0cb1cdSDale Ghent 	u32 speedcnt = 0;
5324dc0cb1cdSDale Ghent 	u32 i = 0;
5325dc0cb1cdSDale Ghent 	bool autoneg, link_up = FALSE;
5326dc0cb1cdSDale Ghent 
5327dc0cb1cdSDale Ghent 	DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber");
5328dc0cb1cdSDale Ghent 
5329dc0cb1cdSDale Ghent 	/* Mask off requested but non-supported speeds */
5330dc0cb1cdSDale Ghent 	status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg);
5331dc0cb1cdSDale Ghent 	if (status != IXGBE_SUCCESS)
5332dc0cb1cdSDale Ghent 		return status;
5333dc0cb1cdSDale Ghent 
5334dc0cb1cdSDale Ghent 	speed &= link_speed;
5335dc0cb1cdSDale Ghent 
5336dc0cb1cdSDale Ghent 	/* Try each speed one by one, highest priority first.  We do this in
5337dc0cb1cdSDale Ghent 	 * software because 10Gb fiber doesn't support speed autonegotiation.
5338dc0cb1cdSDale Ghent 	 */
5339dc0cb1cdSDale Ghent 	if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
5340dc0cb1cdSDale Ghent 		speedcnt++;
5341dc0cb1cdSDale Ghent 		highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
5342dc0cb1cdSDale Ghent 
5343dc0cb1cdSDale Ghent 		/* Set the module link speed */
5344dc0cb1cdSDale Ghent 		switch (hw->phy.media_type) {
5345dc0cb1cdSDale Ghent 		case ixgbe_media_type_fiber_fixed:
5346dc0cb1cdSDale Ghent 		case ixgbe_media_type_fiber:
5347dc0cb1cdSDale Ghent 			ixgbe_set_rate_select_speed(hw,
5348dc0cb1cdSDale Ghent 						    IXGBE_LINK_SPEED_10GB_FULL);
5349dc0cb1cdSDale Ghent 			break;
5350dc0cb1cdSDale Ghent 		case ixgbe_media_type_fiber_qsfp:
5351dc0cb1cdSDale Ghent 			/* QSFP module automatically detects MAC link speed */
5352dc0cb1cdSDale Ghent 			break;
5353dc0cb1cdSDale Ghent 		default:
5354dc0cb1cdSDale Ghent 			DEBUGOUT("Unexpected media type.\n");
5355dc0cb1cdSDale Ghent 			break;
5356dc0cb1cdSDale Ghent 		}
5357dc0cb1cdSDale Ghent 
5358dc0cb1cdSDale Ghent 		/* Allow module to change analog characteristics (1G->10G) */
5359dc0cb1cdSDale Ghent 		msec_delay(40);
5360dc0cb1cdSDale Ghent 
5361dc0cb1cdSDale Ghent 		status = ixgbe_setup_mac_link(hw,
5362dc0cb1cdSDale Ghent 					      IXGBE_LINK_SPEED_10GB_FULL,
5363dc0cb1cdSDale Ghent 					      autoneg_wait_to_complete);
5364dc0cb1cdSDale Ghent 		if (status != IXGBE_SUCCESS)
5365dc0cb1cdSDale Ghent 			return status;
5366dc0cb1cdSDale Ghent 
5367dc0cb1cdSDale Ghent 		/* Flap the Tx laser if it has not already been done */
5368dc0cb1cdSDale Ghent 		ixgbe_flap_tx_laser(hw);
5369dc0cb1cdSDale Ghent 
5370dc0cb1cdSDale Ghent 		/* Wait for the controller to acquire link.  Per IEEE 802.3ap,
5371dc0cb1cdSDale Ghent 		 * Section 73.10.2, we may have to wait up to 500ms if KR is
5372dc0cb1cdSDale Ghent 		 * attempted.  82599 uses the same timing for 10g SFI.
5373dc0cb1cdSDale Ghent 		 */
5374dc0cb1cdSDale Ghent 		for (i = 0; i < 5; i++) {
5375dc0cb1cdSDale Ghent 			/* Wait for the link partner to also set speed */
5376dc0cb1cdSDale Ghent 			msec_delay(100);
5377dc0cb1cdSDale Ghent 
5378dc0cb1cdSDale Ghent 			/* If we have link, just jump out */
5379dc0cb1cdSDale Ghent 			status = ixgbe_check_link(hw, &link_speed,
5380dc0cb1cdSDale Ghent 						  &link_up, FALSE);
5381dc0cb1cdSDale Ghent 			if (status != IXGBE_SUCCESS)
5382dc0cb1cdSDale Ghent 				return status;
5383dc0cb1cdSDale Ghent 
5384dc0cb1cdSDale Ghent 			if (link_up)
5385dc0cb1cdSDale Ghent 				goto out;
5386dc0cb1cdSDale Ghent 		}
5387dc0cb1cdSDale Ghent 	}
5388dc0cb1cdSDale Ghent 
5389dc0cb1cdSDale Ghent 	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
5390dc0cb1cdSDale Ghent 		speedcnt++;
5391dc0cb1cdSDale Ghent 		if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
5392dc0cb1cdSDale Ghent 			highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
5393dc0cb1cdSDale Ghent 
5394dc0cb1cdSDale Ghent 		/* Set the module link speed */
5395dc0cb1cdSDale Ghent 		switch (hw->phy.media_type) {
5396dc0cb1cdSDale Ghent 		case ixgbe_media_type_fiber_fixed:
5397dc0cb1cdSDale Ghent 		case ixgbe_media_type_fiber:
5398dc0cb1cdSDale Ghent 			ixgbe_set_rate_select_speed(hw,
5399dc0cb1cdSDale Ghent 						    IXGBE_LINK_SPEED_1GB_FULL);
5400dc0cb1cdSDale Ghent 			break;
5401dc0cb1cdSDale Ghent 		case ixgbe_media_type_fiber_qsfp:
5402dc0cb1cdSDale Ghent 			/* QSFP module automatically detects link speed */
5403dc0cb1cdSDale Ghent 			break;
5404dc0cb1cdSDale Ghent 		default:
5405dc0cb1cdSDale Ghent 			DEBUGOUT("Unexpected media type.\n");
5406dc0cb1cdSDale Ghent 			break;
5407dc0cb1cdSDale Ghent 		}
5408dc0cb1cdSDale Ghent 
5409dc0cb1cdSDale Ghent 		/* Allow module to change analog characteristics (10G->1G) */
5410dc0cb1cdSDale Ghent 		msec_delay(40);
5411dc0cb1cdSDale Ghent 
5412dc0cb1cdSDale Ghent 		status = ixgbe_setup_mac_link(hw,
5413dc0cb1cdSDale Ghent 					      IXGBE_LINK_SPEED_1GB_FULL,
5414dc0cb1cdSDale Ghent 					      autoneg_wait_to_complete);
5415dc0cb1cdSDale Ghent 		if (status != IXGBE_SUCCESS)
5416dc0cb1cdSDale Ghent 			return status;
5417dc0cb1cdSDale Ghent 
5418dc0cb1cdSDale Ghent 		/* Flap the Tx laser if it has not already been done */
5419dc0cb1cdSDale Ghent 		ixgbe_flap_tx_laser(hw);
5420dc0cb1cdSDale Ghent 
5421dc0cb1cdSDale Ghent 		/* Wait for the link partner to also set speed */
5422dc0cb1cdSDale Ghent 		msec_delay(100);
5423dc0cb1cdSDale Ghent 
5424dc0cb1cdSDale Ghent 		/* If we have link, just jump out */
5425dc0cb1cdSDale Ghent 		status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
5426dc0cb1cdSDale Ghent 		if (status != IXGBE_SUCCESS)
5427dc0cb1cdSDale Ghent 			return status;
5428dc0cb1cdSDale Ghent 
5429dc0cb1cdSDale Ghent 		if (link_up)
5430dc0cb1cdSDale Ghent 			goto out;
5431dc0cb1cdSDale Ghent 	}
5432dc0cb1cdSDale Ghent 
5433dc0cb1cdSDale Ghent 	/* We didn't get link.  Configure back to the highest speed we tried,
5434dc0cb1cdSDale Ghent 	 * (if there was more than one).  We call ourselves back with just the
5435dc0cb1cdSDale Ghent 	 * single highest speed that the user requested.
5436dc0cb1cdSDale Ghent 	 */
5437dc0cb1cdSDale Ghent 	if (speedcnt > 1)
5438dc0cb1cdSDale Ghent 		status = ixgbe_setup_mac_link_multispeed_fiber(hw,
5439dc0cb1cdSDale Ghent 						      highest_link_speed,
5440dc0cb1cdSDale Ghent 						      autoneg_wait_to_complete);
5441dc0cb1cdSDale Ghent 
5442dc0cb1cdSDale Ghent out:
5443dc0cb1cdSDale Ghent 	/* Set autoneg_advertised value based on input link speed */
5444dc0cb1cdSDale Ghent 	hw->phy.autoneg_advertised = 0;
5445dc0cb1cdSDale Ghent 
5446dc0cb1cdSDale Ghent 	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
5447dc0cb1cdSDale Ghent 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
5448dc0cb1cdSDale Ghent 
5449dc0cb1cdSDale Ghent 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
5450dc0cb1cdSDale Ghent 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
5451dc0cb1cdSDale Ghent 
5452dc0cb1cdSDale Ghent 	return status;
5453dc0cb1cdSDale Ghent }
5454dc0cb1cdSDale Ghent 
5455dc0cb1cdSDale Ghent /**
5456dc0cb1cdSDale Ghent  *  ixgbe_set_soft_rate_select_speed - Set module link speed
5457dc0cb1cdSDale Ghent  *  @hw: pointer to hardware structure
5458dc0cb1cdSDale Ghent  *  @speed: link speed to set
5459dc0cb1cdSDale Ghent  *
5460dc0cb1cdSDale Ghent  *  Set module link speed via the soft rate select.
5461dc0cb1cdSDale Ghent  */
ixgbe_set_soft_rate_select_speed(struct ixgbe_hw * hw,ixgbe_link_speed speed)5462dc0cb1cdSDale Ghent void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw,
5463dc0cb1cdSDale Ghent 					ixgbe_link_speed speed)
5464dc0cb1cdSDale Ghent {
5465dc0cb1cdSDale Ghent 	s32 status;
5466dc0cb1cdSDale Ghent 	u8 rs, eeprom_data;
5467dc0cb1cdSDale Ghent 
5468dc0cb1cdSDale Ghent 	switch (speed) {
5469dc0cb1cdSDale Ghent 	case IXGBE_LINK_SPEED_10GB_FULL:
5470dc0cb1cdSDale Ghent 		/* one bit mask same as setting on */
5471dc0cb1cdSDale Ghent 		rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
5472dc0cb1cdSDale Ghent 		break;
5473dc0cb1cdSDale Ghent 	case IXGBE_LINK_SPEED_1GB_FULL:
5474dc0cb1cdSDale Ghent 		rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
5475dc0cb1cdSDale Ghent 		break;
5476dc0cb1cdSDale Ghent 	default:
5477dc0cb1cdSDale Ghent 		DEBUGOUT("Invalid fixed module speed\n");
5478dc0cb1cdSDale Ghent 		return;
5479dc0cb1cdSDale Ghent 	}
5480dc0cb1cdSDale Ghent 
5481dc0cb1cdSDale Ghent 	/* Set RS0 */
5482dc0cb1cdSDale Ghent 	status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
5483dc0cb1cdSDale Ghent 					   IXGBE_I2C_EEPROM_DEV_ADDR2,
5484dc0cb1cdSDale Ghent 					   &eeprom_data);
5485dc0cb1cdSDale Ghent 	if (status) {
5486dc0cb1cdSDale Ghent 		DEBUGOUT("Failed to read Rx Rate Select RS0\n");
5487dc0cb1cdSDale Ghent 		goto out;
5488dc0cb1cdSDale Ghent 	}
5489dc0cb1cdSDale Ghent 
5490dc0cb1cdSDale Ghent 	eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs;
5491dc0cb1cdSDale Ghent 
5492dc0cb1cdSDale Ghent 	status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
5493dc0cb1cdSDale Ghent 					    IXGBE_I2C_EEPROM_DEV_ADDR2,
5494dc0cb1cdSDale Ghent 					    eeprom_data);
5495dc0cb1cdSDale Ghent 	if (status) {
5496dc0cb1cdSDale Ghent 		DEBUGOUT("Failed to write Rx Rate Select RS0\n");
5497dc0cb1cdSDale Ghent 		goto out;
5498dc0cb1cdSDale Ghent 	}
5499dc0cb1cdSDale Ghent 
5500dc0cb1cdSDale Ghent 	/* Set RS1 */
5501dc0cb1cdSDale Ghent 	status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
5502dc0cb1cdSDale Ghent 					   IXGBE_I2C_EEPROM_DEV_ADDR2,
5503dc0cb1cdSDale Ghent 					   &eeprom_data);
5504dc0cb1cdSDale Ghent 	if (status) {
5505dc0cb1cdSDale Ghent 		DEBUGOUT("Failed to read Rx Rate Select RS1\n");
5506dc0cb1cdSDale Ghent 		goto out;
5507dc0cb1cdSDale Ghent 	}
5508dc0cb1cdSDale Ghent 
5509dc0cb1cdSDale Ghent 	eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs;
5510dc0cb1cdSDale Ghent 
5511dc0cb1cdSDale Ghent 	status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
5512dc0cb1cdSDale Ghent 					    IXGBE_I2C_EEPROM_DEV_ADDR2,
5513dc0cb1cdSDale Ghent 					    eeprom_data);
5514dc0cb1cdSDale Ghent 	if (status) {
5515dc0cb1cdSDale Ghent 		DEBUGOUT("Failed to write Rx Rate Select RS1\n");
5516dc0cb1cdSDale Ghent 		goto out;
5517dc0cb1cdSDale Ghent 	}
5518dc0cb1cdSDale Ghent out:
5519dc0cb1cdSDale Ghent 	return;
5520dc0cb1cdSDale Ghent }
5521