xref: /freebsd/sys/dev/ixgbe/ixgbe_common.c (revision 1a4e34498c7974f82de35c4e309338cb9387b5c1)
19ca4041bSJack F Vogel /******************************************************************************
213705f88SJack F Vogel 
3c0014855SJack F Vogel   Copyright (c) 2001-2010, Intel Corporation
413705f88SJack F Vogel   All rights reserved.
513705f88SJack F Vogel 
613705f88SJack F Vogel   Redistribution and use in source and binary forms, with or without
713705f88SJack F Vogel   modification, are permitted provided that the following conditions are met:
813705f88SJack F Vogel 
913705f88SJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
1013705f88SJack F Vogel       this list of conditions and the following disclaimer.
1113705f88SJack F Vogel 
1213705f88SJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
1313705f88SJack F Vogel       notice, this list of conditions and the following disclaimer in the
1413705f88SJack F Vogel       documentation and/or other materials provided with the distribution.
1513705f88SJack F Vogel 
1613705f88SJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
1713705f88SJack F Vogel       contributors may be used to endorse or promote products derived from
1813705f88SJack F Vogel       this software without specific prior written permission.
1913705f88SJack F Vogel 
2013705f88SJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2113705f88SJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2213705f88SJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2313705f88SJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2413705f88SJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2513705f88SJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2613705f88SJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2713705f88SJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2813705f88SJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2913705f88SJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3013705f88SJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
3113705f88SJack F Vogel 
329ca4041bSJack F Vogel ******************************************************************************/
3313705f88SJack F Vogel /*$FreeBSD$*/
3413705f88SJack F Vogel 
3513705f88SJack F Vogel #include "ixgbe_common.h"
36*1a4e3449SJack F Vogel #include "ixgbe_phy.h"
3713705f88SJack F Vogel #include "ixgbe_api.h"
3813705f88SJack F Vogel 
3913705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
4013705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
4113705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
4213705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw);
4313705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw);
4413705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
4513705f88SJack F Vogel                                         u16 count);
4613705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count);
4713705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
4813705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
4913705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
5013705f88SJack F Vogel 
5113705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
522969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
532969bf0eSJack F Vogel                                         u16 *san_mac_offset);
54*1a4e3449SJack F Vogel static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw);
55*1a4e3449SJack F Vogel static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw);
56*1a4e3449SJack F Vogel static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw);
57*1a4e3449SJack F Vogel static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
58*1a4e3449SJack F Vogel static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
59*1a4e3449SJack F Vogel 			      u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
60*1a4e3449SJack F Vogel 
612969bf0eSJack F Vogel s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan);
6213705f88SJack F Vogel 
6313705f88SJack F Vogel /**
649ca4041bSJack F Vogel  *  ixgbe_init_ops_generic - Inits function ptrs
659ca4041bSJack F Vogel  *  @hw: pointer to the hardware structure
6613705f88SJack F Vogel  *
679ca4041bSJack F Vogel  *  Initialize the function pointers.
6813705f88SJack F Vogel  **/
699ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
7013705f88SJack F Vogel {
719ca4041bSJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
729ca4041bSJack F Vogel 	struct ixgbe_mac_info *mac = &hw->mac;
739ca4041bSJack F Vogel 	u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
7413705f88SJack F Vogel 
752969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_ops_generic");
762969bf0eSJack F Vogel 
7713705f88SJack F Vogel 	/* EEPROM */
789ca4041bSJack F Vogel 	eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic;
799ca4041bSJack F Vogel 	/* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
809ca4041bSJack F Vogel 	if (eec & (1 << 8))
812969bf0eSJack F Vogel 		eeprom->ops.read = &ixgbe_read_eerd_generic;
829ca4041bSJack F Vogel 	else
839ca4041bSJack F Vogel 		eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic;
849ca4041bSJack F Vogel 	eeprom->ops.write = &ixgbe_write_eeprom_generic;
859ca4041bSJack F Vogel 	eeprom->ops.validate_checksum =
8613705f88SJack F Vogel 	                              &ixgbe_validate_eeprom_checksum_generic;
879ca4041bSJack F Vogel 	eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic;
882969bf0eSJack F Vogel 	eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_generic;
899ca4041bSJack F Vogel 
909ca4041bSJack F Vogel 	/* MAC */
919ca4041bSJack F Vogel 	mac->ops.init_hw = &ixgbe_init_hw_generic;
929ca4041bSJack F Vogel 	mac->ops.reset_hw = NULL;
939ca4041bSJack F Vogel 	mac->ops.start_hw = &ixgbe_start_hw_generic;
949ca4041bSJack F Vogel 	mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic;
959ca4041bSJack F Vogel 	mac->ops.get_media_type = NULL;
961b6e0dbaSJack F Vogel 	mac->ops.get_supported_physical_layer = NULL;
970ac6dfecSJack F Vogel 	mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic;
989ca4041bSJack F Vogel 	mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic;
999ca4041bSJack F Vogel 	mac->ops.stop_adapter = &ixgbe_stop_adapter_generic;
1009ca4041bSJack F Vogel 	mac->ops.get_bus_info = &ixgbe_get_bus_info_generic;
1011b6e0dbaSJack F Vogel 	mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie;
102d8602bb9SJack F Vogel 	mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync;
103d8602bb9SJack F Vogel 	mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync;
1049ca4041bSJack F Vogel 
1059ca4041bSJack F Vogel 	/* LEDs */
1069ca4041bSJack F Vogel 	mac->ops.led_on = &ixgbe_led_on_generic;
1079ca4041bSJack F Vogel 	mac->ops.led_off = &ixgbe_led_off_generic;
1080ac6dfecSJack F Vogel 	mac->ops.blink_led_start = &ixgbe_blink_led_start_generic;
1090ac6dfecSJack F Vogel 	mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic;
1109ca4041bSJack F Vogel 
11113705f88SJack F Vogel 	/* RAR, Multicast, VLAN */
1129ca4041bSJack F Vogel 	mac->ops.set_rar = &ixgbe_set_rar_generic;
1135b7f4cedSJack F Vogel 	mac->ops.clear_rar = &ixgbe_clear_rar_generic;
1140ac6dfecSJack F Vogel 	mac->ops.insert_mac_addr = NULL;
1159ca4041bSJack F Vogel 	mac->ops.set_vmdq = NULL;
1165b7f4cedSJack F Vogel 	mac->ops.clear_vmdq = NULL;
1179ca4041bSJack F Vogel 	mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic;
1189ca4041bSJack F Vogel 	mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic;
1199ca4041bSJack F Vogel 	mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic;
1209ca4041bSJack F Vogel 	mac->ops.enable_mc = &ixgbe_enable_mc_generic;
1219ca4041bSJack F Vogel 	mac->ops.disable_mc = &ixgbe_disable_mc_generic;
1225b7f4cedSJack F Vogel 	mac->ops.clear_vfta = NULL;
1235b7f4cedSJack F Vogel 	mac->ops.set_vfta = NULL;
1245b7f4cedSJack F Vogel 	mac->ops.init_uta_tables = NULL;
1259ca4041bSJack F Vogel 
1260ac6dfecSJack F Vogel 	/* Flow Control */
1270ac6dfecSJack F Vogel 	mac->ops.fc_enable = &ixgbe_fc_enable_generic;
1289ca4041bSJack F Vogel 
1299ca4041bSJack F Vogel 	/* Link */
1309ca4041bSJack F Vogel 	mac->ops.get_link_capabilities = NULL;
1319ca4041bSJack F Vogel 	mac->ops.setup_link = NULL;
1329ca4041bSJack F Vogel 	mac->ops.check_link = NULL;
13313705f88SJack F Vogel 
13413705f88SJack F Vogel 	return IXGBE_SUCCESS;
13513705f88SJack F Vogel }
13613705f88SJack F Vogel 
13713705f88SJack F Vogel /**
1389ca4041bSJack F Vogel  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
13913705f88SJack F Vogel  *  @hw: pointer to hardware structure
14013705f88SJack F Vogel  *
14113705f88SJack F Vogel  *  Starts the hardware by filling the bus info structure and media type, clears
14213705f88SJack F Vogel  *  all on chip counters, initializes receive address registers, multicast
14313705f88SJack F Vogel  *  table, VLAN filter table, calls routine to set up link and flow control
14413705f88SJack F Vogel  *  settings, and leaves transmit and receive units disabled and uninitialized
14513705f88SJack F Vogel  **/
14613705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
14713705f88SJack F Vogel {
14813705f88SJack F Vogel 	u32 ctrl_ext;
14913705f88SJack F Vogel 
1502969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_start_hw_generic");
1512969bf0eSJack F Vogel 
15213705f88SJack F Vogel 	/* Set the media type */
1539ca4041bSJack F Vogel 	hw->phy.media_type = hw->mac.ops.get_media_type(hw);
15413705f88SJack F Vogel 
1550ac6dfecSJack F Vogel 	/* PHY ops initialization must be done in reset_hw() */
15613705f88SJack F Vogel 
15713705f88SJack F Vogel 	/* Clear the VLAN filter table */
1589ca4041bSJack F Vogel 	hw->mac.ops.clear_vfta(hw);
15913705f88SJack F Vogel 
16013705f88SJack F Vogel 	/* Clear statistics registers */
1619ca4041bSJack F Vogel 	hw->mac.ops.clear_hw_cntrs(hw);
16213705f88SJack F Vogel 
16313705f88SJack F Vogel 	/* Set No Snoop Disable */
16413705f88SJack F Vogel 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
16513705f88SJack F Vogel 	ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
16613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
1679ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
16813705f88SJack F Vogel 
1690ac6dfecSJack F Vogel 	/* Setup flow control */
1700ac6dfecSJack F Vogel 	ixgbe_setup_fc(hw, 0);
1710ac6dfecSJack F Vogel 
17213705f88SJack F Vogel 	/* Clear adapter stopped flag */
17313705f88SJack F Vogel 	hw->adapter_stopped = FALSE;
17413705f88SJack F Vogel 
175*1a4e3449SJack F Vogel 	return IXGBE_SUCCESS;
176*1a4e3449SJack F Vogel }
177*1a4e3449SJack F Vogel 
178*1a4e3449SJack F Vogel /**
179*1a4e3449SJack F Vogel  *  ixgbe_start_hw_gen2 - Init sequence for common device family
180*1a4e3449SJack F Vogel  *  @hw: pointer to hw structure
181*1a4e3449SJack F Vogel  *
182*1a4e3449SJack F Vogel  * Performs the init sequence common to the second generation
183*1a4e3449SJack F Vogel  * of 10 GbE devices.
184*1a4e3449SJack F Vogel  * Devices in the second generation:
185*1a4e3449SJack F Vogel  *     82599
186*1a4e3449SJack F Vogel  **/
187*1a4e3449SJack F Vogel s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw)
188*1a4e3449SJack F Vogel {
189*1a4e3449SJack F Vogel 	u32 i;
190*1a4e3449SJack F Vogel 	u32 regval;
191*1a4e3449SJack F Vogel 
192*1a4e3449SJack F Vogel 	/* Clear the rate limiters */
193*1a4e3449SJack F Vogel 	for (i = 0; i < hw->mac.max_tx_queues; i++) {
194*1a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i);
195*1a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0);
196*1a4e3449SJack F Vogel 	}
197*1a4e3449SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
198*1a4e3449SJack F Vogel 
199*1a4e3449SJack F Vogel 	/* Disable relaxed ordering */
200*1a4e3449SJack F Vogel 	for (i = 0; i < hw->mac.max_tx_queues; i++) {
201*1a4e3449SJack F Vogel 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
202*1a4e3449SJack F Vogel 		regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
203*1a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
204*1a4e3449SJack F Vogel 	}
205*1a4e3449SJack F Vogel 
206*1a4e3449SJack F Vogel 	for (i = 0; i < hw->mac.max_rx_queues; i++) {
207*1a4e3449SJack F Vogel 		regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
208*1a4e3449SJack F Vogel 		regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
209*1a4e3449SJack F Vogel 					IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
210*1a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
211*1a4e3449SJack F Vogel 	}
212*1a4e3449SJack F Vogel 
213*1a4e3449SJack F Vogel 	return IXGBE_SUCCESS;
21413705f88SJack F Vogel }
21513705f88SJack F Vogel 
21613705f88SJack F Vogel /**
21713705f88SJack F Vogel  *  ixgbe_init_hw_generic - Generic hardware initialization
21813705f88SJack F Vogel  *  @hw: pointer to hardware structure
21913705f88SJack F Vogel  *
2209ca4041bSJack F Vogel  *  Initialize the hardware by resetting the hardware, filling the bus info
22113705f88SJack F Vogel  *  structure and media type, clears all on chip counters, initializes receive
22213705f88SJack F Vogel  *  address registers, multicast table, VLAN filter table, calls routine to set
22313705f88SJack F Vogel  *  up link and flow control settings, and leaves transmit and receive units
22413705f88SJack F Vogel  *  disabled and uninitialized
22513705f88SJack F Vogel  **/
22613705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
22713705f88SJack F Vogel {
228*1a4e3449SJack F Vogel 	s32 status;
2290ac6dfecSJack F Vogel 
2302969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_hw_generic");
2312969bf0eSJack F Vogel 
23213705f88SJack F Vogel 	/* Reset the hardware */
2330ac6dfecSJack F Vogel 	status = hw->mac.ops.reset_hw(hw);
23413705f88SJack F Vogel 
2350ac6dfecSJack F Vogel 	if (status == IXGBE_SUCCESS) {
23613705f88SJack F Vogel 		/* Start the HW */
2370ac6dfecSJack F Vogel 		status = hw->mac.ops.start_hw(hw);
2380ac6dfecSJack F Vogel 	}
23913705f88SJack F Vogel 
2400ac6dfecSJack F Vogel 	return status;
24113705f88SJack F Vogel }
24213705f88SJack F Vogel 
24313705f88SJack F Vogel /**
24413705f88SJack F Vogel  *  ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
24513705f88SJack F Vogel  *  @hw: pointer to hardware structure
24613705f88SJack F Vogel  *
24713705f88SJack F Vogel  *  Clears all hardware statistics counters by reading them from the hardware
24813705f88SJack F Vogel  *  Statistics counters are clear on read.
24913705f88SJack F Vogel  **/
25013705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
25113705f88SJack F Vogel {
25213705f88SJack F Vogel 	u16 i = 0;
25313705f88SJack F Vogel 
2542969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_clear_hw_cntrs_generic");
2552969bf0eSJack F Vogel 
25613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_CRCERRS);
25713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ILLERRC);
25813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ERRBC);
25913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MSPDC);
26013705f88SJack F Vogel 	for (i = 0; i < 8; i++)
26113705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_MPC(i));
26213705f88SJack F Vogel 
26313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MLFC);
26413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MRFC);
26513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RLEC);
26613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXONTXC);
26713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
2680ac6dfecSJack F Vogel 	if (hw->mac.type >= ixgbe_mac_82599EB) {
2690ac6dfecSJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
2700ac6dfecSJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
2710ac6dfecSJack F Vogel 	} else {
2721b6e0dbaSJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_LXONRXC);
27313705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
2740ac6dfecSJack F Vogel 	}
27513705f88SJack F Vogel 
27613705f88SJack F Vogel 	for (i = 0; i < 8; i++) {
27713705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
27813705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
2790ac6dfecSJack F Vogel 		if (hw->mac.type >= ixgbe_mac_82599EB) {
2800ac6dfecSJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
2810ac6dfecSJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
2820ac6dfecSJack F Vogel 		} else {
2831b6e0dbaSJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
28413705f88SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
28513705f88SJack F Vogel 		}
2860ac6dfecSJack F Vogel 	}
2870ac6dfecSJack F Vogel 	if (hw->mac.type >= ixgbe_mac_82599EB)
2880ac6dfecSJack F Vogel 		for (i = 0; i < 8; i++)
2890ac6dfecSJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
29013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC64);
29113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC127);
29213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC255);
29313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC511);
29413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC1023);
29513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC1522);
29613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GPRC);
29713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_BPRC);
29813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MPRC);
29913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GPTC);
30013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GORCL);
30113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GORCH);
30213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GOTCL);
30313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GOTCH);
30413705f88SJack F Vogel 	for (i = 0; i < 8; i++)
30513705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_RNBC(i));
30613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RUC);
30713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RFC);
30813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ROC);
30913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RJC);
31013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPRC);
31113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPDC);
31213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPTC);
31313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TORL);
31413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TORH);
31513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TPR);
31613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TPT);
31713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC64);
31813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC127);
31913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC255);
32013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC511);
32113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC1023);
32213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC1522);
32313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MPTC);
32413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_BPTC);
32513705f88SJack F Vogel 	for (i = 0; i < 16; i++) {
32613705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QPRC(i));
32713705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QPTC(i));
328*1a4e3449SJack F Vogel 		if (hw->mac.type >= ixgbe_mac_82599EB) {
329*1a4e3449SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
330*1a4e3449SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_QBRC_H(i));
331*1a4e3449SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
332*1a4e3449SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_QBTC_H(i));
333*1a4e3449SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
334*1a4e3449SJack F Vogel 		} else {
335*1a4e3449SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_QBRC(i));
33613705f88SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_QBTC(i));
33713705f88SJack F Vogel 		}
338*1a4e3449SJack F Vogel 	}
339*1a4e3449SJack F Vogel 
340*1a4e3449SJack F Vogel 	return IXGBE_SUCCESS;
341*1a4e3449SJack F Vogel }
342*1a4e3449SJack F Vogel 
343*1a4e3449SJack F Vogel /**
344*1a4e3449SJack F Vogel  *  ixgbe_read_pba_string_generic - Reads part number string from EEPROM
345*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
346*1a4e3449SJack F Vogel  *  @pba_num: stores the part number string from the EEPROM
347*1a4e3449SJack F Vogel  *  @pba_num_size: part number string buffer length
348*1a4e3449SJack F Vogel  *
349*1a4e3449SJack F Vogel  *  Reads the part number string from the EEPROM.
350*1a4e3449SJack F Vogel  **/
351*1a4e3449SJack F Vogel s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num,
352*1a4e3449SJack F Vogel                                   u32 pba_num_size)
353*1a4e3449SJack F Vogel {
354*1a4e3449SJack F Vogel 	s32 ret_val;
355*1a4e3449SJack F Vogel 	u16 data;
356*1a4e3449SJack F Vogel 	u16 pba_ptr;
357*1a4e3449SJack F Vogel 	u16 offset;
358*1a4e3449SJack F Vogel 	u16 length;
359*1a4e3449SJack F Vogel 
360*1a4e3449SJack F Vogel 	DEBUGFUNC("ixgbe_read_pba_string_generic");
361*1a4e3449SJack F Vogel 
362*1a4e3449SJack F Vogel 	if (pba_num == NULL) {
363*1a4e3449SJack F Vogel 		DEBUGOUT("PBA string buffer was null\n");
364*1a4e3449SJack F Vogel 		return IXGBE_ERR_INVALID_ARGUMENT;
365*1a4e3449SJack F Vogel 	}
366*1a4e3449SJack F Vogel 
367*1a4e3449SJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
368*1a4e3449SJack F Vogel 	if (ret_val) {
369*1a4e3449SJack F Vogel 		DEBUGOUT("NVM Read Error\n");
370*1a4e3449SJack F Vogel 		return ret_val;
371*1a4e3449SJack F Vogel 	}
372*1a4e3449SJack F Vogel 
373*1a4e3449SJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr);
374*1a4e3449SJack F Vogel 	if (ret_val) {
375*1a4e3449SJack F Vogel 		DEBUGOUT("NVM Read Error\n");
376*1a4e3449SJack F Vogel 		return ret_val;
377*1a4e3449SJack F Vogel 	}
378*1a4e3449SJack F Vogel 
379*1a4e3449SJack F Vogel 	/*
380*1a4e3449SJack F Vogel 	 * if data is not ptr guard the PBA must be in legacy format which
381*1a4e3449SJack F Vogel 	 * means pba_ptr is actually our second data word for the PBA number
382*1a4e3449SJack F Vogel 	 * and we can decode it into an ascii string
383*1a4e3449SJack F Vogel 	 */
384*1a4e3449SJack F Vogel 	if (data != IXGBE_PBANUM_PTR_GUARD) {
385*1a4e3449SJack F Vogel 		DEBUGOUT("NVM PBA number is not stored as string\n");
386*1a4e3449SJack F Vogel 
387*1a4e3449SJack F Vogel 		/* we will need 11 characters to store the PBA */
388*1a4e3449SJack F Vogel 		if (pba_num_size < 11) {
389*1a4e3449SJack F Vogel 			DEBUGOUT("PBA string buffer too small\n");
390*1a4e3449SJack F Vogel 			return IXGBE_ERR_NO_SPACE;
391*1a4e3449SJack F Vogel 		}
392*1a4e3449SJack F Vogel 
393*1a4e3449SJack F Vogel 		/* extract hex string from data and pba_ptr */
394*1a4e3449SJack F Vogel 		pba_num[0] = (data >> 12) & 0xF;
395*1a4e3449SJack F Vogel 		pba_num[1] = (data >> 8) & 0xF;
396*1a4e3449SJack F Vogel 		pba_num[2] = (data >> 4) & 0xF;
397*1a4e3449SJack F Vogel 		pba_num[3] = data & 0xF;
398*1a4e3449SJack F Vogel 		pba_num[4] = (pba_ptr >> 12) & 0xF;
399*1a4e3449SJack F Vogel 		pba_num[5] = (pba_ptr >> 8) & 0xF;
400*1a4e3449SJack F Vogel 		pba_num[6] = '-';
401*1a4e3449SJack F Vogel 		pba_num[7] = 0;
402*1a4e3449SJack F Vogel 		pba_num[8] = (pba_ptr >> 4) & 0xF;
403*1a4e3449SJack F Vogel 		pba_num[9] = pba_ptr & 0xF;
404*1a4e3449SJack F Vogel 
405*1a4e3449SJack F Vogel 		/* put a null character on the end of our string */
406*1a4e3449SJack F Vogel 		pba_num[10] = '\0';
407*1a4e3449SJack F Vogel 
408*1a4e3449SJack F Vogel 		/* switch all the data but the '-' to hex char */
409*1a4e3449SJack F Vogel 		for (offset = 0; offset < 10; offset++) {
410*1a4e3449SJack F Vogel 			if (pba_num[offset] < 0xA)
411*1a4e3449SJack F Vogel 				pba_num[offset] += '0';
412*1a4e3449SJack F Vogel 			else if (pba_num[offset] < 0x10)
413*1a4e3449SJack F Vogel 				pba_num[offset] += 'A' - 0xA;
414*1a4e3449SJack F Vogel 		}
415*1a4e3449SJack F Vogel 
416*1a4e3449SJack F Vogel 		return IXGBE_SUCCESS;
417*1a4e3449SJack F Vogel 	}
418*1a4e3449SJack F Vogel 
419*1a4e3449SJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length);
420*1a4e3449SJack F Vogel 	if (ret_val) {
421*1a4e3449SJack F Vogel 		DEBUGOUT("NVM Read Error\n");
422*1a4e3449SJack F Vogel 		return ret_val;
423*1a4e3449SJack F Vogel 	}
424*1a4e3449SJack F Vogel 
425*1a4e3449SJack F Vogel 	if (length == 0xFFFF || length == 0) {
426*1a4e3449SJack F Vogel 		DEBUGOUT("NVM PBA number section invalid length\n");
427*1a4e3449SJack F Vogel 		return IXGBE_ERR_PBA_SECTION;
428*1a4e3449SJack F Vogel 	}
429*1a4e3449SJack F Vogel 
430*1a4e3449SJack F Vogel 	/* check if pba_num buffer is big enough */
431*1a4e3449SJack F Vogel 	if (pba_num_size  < (((u32)length * 2) - 1)) {
432*1a4e3449SJack F Vogel 		DEBUGOUT("PBA string buffer too small\n");
433*1a4e3449SJack F Vogel 		return IXGBE_ERR_NO_SPACE;
434*1a4e3449SJack F Vogel 	}
435*1a4e3449SJack F Vogel 
436*1a4e3449SJack F Vogel 	/* trim pba length from start of string */
437*1a4e3449SJack F Vogel 	pba_ptr++;
438*1a4e3449SJack F Vogel 	length--;
439*1a4e3449SJack F Vogel 
440*1a4e3449SJack F Vogel 	for (offset = 0; offset < length; offset++) {
441*1a4e3449SJack F Vogel 		ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data);
442*1a4e3449SJack F Vogel 		if (ret_val) {
443*1a4e3449SJack F Vogel 			DEBUGOUT("NVM Read Error\n");
444*1a4e3449SJack F Vogel 			return ret_val;
445*1a4e3449SJack F Vogel 		}
446*1a4e3449SJack F Vogel 		pba_num[offset * 2] = (u8)(data >> 8);
447*1a4e3449SJack F Vogel 		pba_num[(offset * 2) + 1] = (u8)(data & 0xFF);
448*1a4e3449SJack F Vogel 	}
449*1a4e3449SJack F Vogel 	pba_num[offset * 2] = '\0';
450*1a4e3449SJack F Vogel 
451*1a4e3449SJack F Vogel 	return IXGBE_SUCCESS;
452*1a4e3449SJack F Vogel }
453*1a4e3449SJack F Vogel 
454*1a4e3449SJack F Vogel /**
455*1a4e3449SJack F Vogel  *  ixgbe_read_pba_length_generic - Reads part number length from EEPROM
456*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
457*1a4e3449SJack F Vogel  *  @pba_num_size: part number string buffer length
458*1a4e3449SJack F Vogel  *
459*1a4e3449SJack F Vogel  *  Reads the part number length from the EEPROM.
460*1a4e3449SJack F Vogel  *  Returns expected buffer size in pba_num_size
461*1a4e3449SJack F Vogel  **/
462*1a4e3449SJack F Vogel s32 ixgbe_read_pba_length_generic(struct ixgbe_hw *hw, u32 *pba_num_size)
463*1a4e3449SJack F Vogel {
464*1a4e3449SJack F Vogel 	s32 ret_val;
465*1a4e3449SJack F Vogel 	u16 data;
466*1a4e3449SJack F Vogel 	u16 pba_ptr;
467*1a4e3449SJack F Vogel 	u16 length;
468*1a4e3449SJack F Vogel 
469*1a4e3449SJack F Vogel 	DEBUGFUNC("ixgbe_read_pba_length_generic");
470*1a4e3449SJack F Vogel 
471*1a4e3449SJack F Vogel 	if (pba_num_size == NULL) {
472*1a4e3449SJack F Vogel 		DEBUGOUT("PBA buffer size was null\n");
473*1a4e3449SJack F Vogel 		return IXGBE_ERR_INVALID_ARGUMENT;
474*1a4e3449SJack F Vogel 	}
475*1a4e3449SJack F Vogel 
476*1a4e3449SJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
477*1a4e3449SJack F Vogel 	if (ret_val) {
478*1a4e3449SJack F Vogel 		DEBUGOUT("NVM Read Error\n");
479*1a4e3449SJack F Vogel 		return ret_val;
480*1a4e3449SJack F Vogel 	}
481*1a4e3449SJack F Vogel 
482*1a4e3449SJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr);
483*1a4e3449SJack F Vogel 	if (ret_val) {
484*1a4e3449SJack F Vogel 		DEBUGOUT("NVM Read Error\n");
485*1a4e3449SJack F Vogel 		return ret_val;
486*1a4e3449SJack F Vogel 	}
487*1a4e3449SJack F Vogel 
488*1a4e3449SJack F Vogel 	 /* if data is not ptr guard the PBA must be in legacy format */
489*1a4e3449SJack F Vogel 	if (data != IXGBE_PBANUM_PTR_GUARD) {
490*1a4e3449SJack F Vogel 		*pba_num_size = 11;
491*1a4e3449SJack F Vogel 		return IXGBE_SUCCESS;
492*1a4e3449SJack F Vogel 	}
493*1a4e3449SJack F Vogel 
494*1a4e3449SJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length);
495*1a4e3449SJack F Vogel 	if (ret_val) {
496*1a4e3449SJack F Vogel 		DEBUGOUT("NVM Read Error\n");
497*1a4e3449SJack F Vogel 		return ret_val;
498*1a4e3449SJack F Vogel 	}
499*1a4e3449SJack F Vogel 
500*1a4e3449SJack F Vogel 	if (length == 0xFFFF || length == 0) {
501*1a4e3449SJack F Vogel 		DEBUGOUT("NVM PBA number section invalid length\n");
502*1a4e3449SJack F Vogel 		return IXGBE_ERR_PBA_SECTION;
503*1a4e3449SJack F Vogel 	}
504*1a4e3449SJack F Vogel 
505*1a4e3449SJack F Vogel 	/*
506*1a4e3449SJack F Vogel 	 * Convert from length in u16 values to u8 chars, add 1 for NULL,
507*1a4e3449SJack F Vogel 	 * and subtract 2 because length field is included in length.
508*1a4e3449SJack F Vogel 	 */
509*1a4e3449SJack F Vogel 	*pba_num_size = ((u32)length * 2) - 1;
51013705f88SJack F Vogel 
51113705f88SJack F Vogel 	return IXGBE_SUCCESS;
51213705f88SJack F Vogel }
51313705f88SJack F Vogel 
51413705f88SJack F Vogel /**
5151b6e0dbaSJack F Vogel  *  ixgbe_read_pba_num_generic - Reads part number from EEPROM
5169ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
5179ca4041bSJack F Vogel  *  @pba_num: stores the part number from the EEPROM
5189ca4041bSJack F Vogel  *
5199ca4041bSJack F Vogel  *  Reads the part number from the EEPROM.
5209ca4041bSJack F Vogel  **/
5219ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num)
5229ca4041bSJack F Vogel {
5239ca4041bSJack F Vogel 	s32 ret_val;
5249ca4041bSJack F Vogel 	u16 data;
5259ca4041bSJack F Vogel 
5269ca4041bSJack F Vogel 	DEBUGFUNC("ixgbe_read_pba_num_generic");
5279ca4041bSJack F Vogel 
5289ca4041bSJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
5299ca4041bSJack F Vogel 	if (ret_val) {
5309ca4041bSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
5319ca4041bSJack F Vogel 		return ret_val;
532*1a4e3449SJack F Vogel 	} else if (data == IXGBE_PBANUM_PTR_GUARD) {
533*1a4e3449SJack F Vogel 		DEBUGOUT("NVM Not supported\n");
534*1a4e3449SJack F Vogel 		return IXGBE_NOT_IMPLEMENTED;
5359ca4041bSJack F Vogel 	}
5369ca4041bSJack F Vogel 	*pba_num = (u32)(data << 16);
5379ca4041bSJack F Vogel 
5389ca4041bSJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data);
5399ca4041bSJack F Vogel 	if (ret_val) {
5409ca4041bSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
5419ca4041bSJack F Vogel 		return ret_val;
5429ca4041bSJack F Vogel 	}
5439ca4041bSJack F Vogel 	*pba_num |= data;
5449ca4041bSJack F Vogel 
5459ca4041bSJack F Vogel 	return IXGBE_SUCCESS;
5469ca4041bSJack F Vogel }
5479ca4041bSJack F Vogel 
5489ca4041bSJack F Vogel /**
54913705f88SJack F Vogel  *  ixgbe_get_mac_addr_generic - Generic get MAC address
55013705f88SJack F Vogel  *  @hw: pointer to hardware structure
55113705f88SJack F Vogel  *  @mac_addr: Adapter MAC address
55213705f88SJack F Vogel  *
55313705f88SJack F Vogel  *  Reads the adapter's MAC address from first Receive Address Register (RAR0)
55413705f88SJack F Vogel  *  A reset of the adapter must be performed prior to calling this function
55513705f88SJack F Vogel  *  in order for the MAC address to have been loaded from the EEPROM into RAR0
55613705f88SJack F Vogel  **/
55713705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
55813705f88SJack F Vogel {
55913705f88SJack F Vogel 	u32 rar_high;
56013705f88SJack F Vogel 	u32 rar_low;
56113705f88SJack F Vogel 	u16 i;
56213705f88SJack F Vogel 
5632969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_mac_addr_generic");
5642969bf0eSJack F Vogel 
56513705f88SJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0));
56613705f88SJack F Vogel 	rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0));
56713705f88SJack F Vogel 
56813705f88SJack F Vogel 	for (i = 0; i < 4; i++)
56913705f88SJack F Vogel 		mac_addr[i] = (u8)(rar_low >> (i*8));
57013705f88SJack F Vogel 
57113705f88SJack F Vogel 	for (i = 0; i < 2; i++)
57213705f88SJack F Vogel 		mac_addr[i+4] = (u8)(rar_high >> (i*8));
57313705f88SJack F Vogel 
57413705f88SJack F Vogel 	return IXGBE_SUCCESS;
57513705f88SJack F Vogel }
57613705f88SJack F Vogel 
57713705f88SJack F Vogel /**
57813705f88SJack F Vogel  *  ixgbe_get_bus_info_generic - Generic set PCI bus info
57913705f88SJack F Vogel  *  @hw: pointer to hardware structure
58013705f88SJack F Vogel  *
58113705f88SJack F Vogel  *  Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure
58213705f88SJack F Vogel  **/
58313705f88SJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
58413705f88SJack F Vogel {
5851b6e0dbaSJack F Vogel 	struct ixgbe_mac_info *mac = &hw->mac;
58613705f88SJack F Vogel 	u16 link_status;
58713705f88SJack F Vogel 
5882969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_bus_info_generic");
5892969bf0eSJack F Vogel 
59013705f88SJack F Vogel 	hw->bus.type = ixgbe_bus_type_pci_express;
59113705f88SJack F Vogel 
59213705f88SJack F Vogel 	/* Get the negotiated link width and speed from PCI config space */
59313705f88SJack F Vogel 	link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS);
59413705f88SJack F Vogel 
59513705f88SJack F Vogel 	switch (link_status & IXGBE_PCI_LINK_WIDTH) {
59613705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_1:
59713705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x1;
59813705f88SJack F Vogel 		break;
59913705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_2:
60013705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x2;
60113705f88SJack F Vogel 		break;
60213705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_4:
60313705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x4;
60413705f88SJack F Vogel 		break;
60513705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_8:
60613705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x8;
60713705f88SJack F Vogel 		break;
60813705f88SJack F Vogel 	default:
60913705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_unknown;
61013705f88SJack F Vogel 		break;
61113705f88SJack F Vogel 	}
61213705f88SJack F Vogel 
61313705f88SJack F Vogel 	switch (link_status & IXGBE_PCI_LINK_SPEED) {
61413705f88SJack F Vogel 	case IXGBE_PCI_LINK_SPEED_2500:
61513705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_2500;
61613705f88SJack F Vogel 		break;
61713705f88SJack F Vogel 	case IXGBE_PCI_LINK_SPEED_5000:
61813705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_5000;
61913705f88SJack F Vogel 		break;
62013705f88SJack F Vogel 	default:
62113705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_unknown;
62213705f88SJack F Vogel 		break;
62313705f88SJack F Vogel 	}
62413705f88SJack F Vogel 
6251b6e0dbaSJack F Vogel 	mac->ops.set_lan_id(hw);
6261b6e0dbaSJack F Vogel 
62713705f88SJack F Vogel 	return IXGBE_SUCCESS;
62813705f88SJack F Vogel }
62913705f88SJack F Vogel 
63013705f88SJack F Vogel /**
6311b6e0dbaSJack F Vogel  *  ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
6321b6e0dbaSJack F Vogel  *  @hw: pointer to the HW structure
6331b6e0dbaSJack F Vogel  *
6341b6e0dbaSJack F Vogel  *  Determines the LAN function id by reading memory-mapped registers
6351b6e0dbaSJack F Vogel  *  and swaps the port value if requested.
6361b6e0dbaSJack F Vogel  **/
6371b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
6381b6e0dbaSJack F Vogel {
6391b6e0dbaSJack F Vogel 	struct ixgbe_bus_info *bus = &hw->bus;
6401b6e0dbaSJack F Vogel 	u32 reg;
6411b6e0dbaSJack F Vogel 
6422969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
6432969bf0eSJack F Vogel 
6441b6e0dbaSJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_STATUS);
6451b6e0dbaSJack F Vogel 	bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT;
6460ac6dfecSJack F Vogel 	bus->lan_id = bus->func;
6471b6e0dbaSJack F Vogel 
6481b6e0dbaSJack F Vogel 	/* check for a port swap */
6491b6e0dbaSJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_FACTPS);
6501b6e0dbaSJack F Vogel 	if (reg & IXGBE_FACTPS_LFS)
6511b6e0dbaSJack F Vogel 		bus->func ^= 0x1;
6521b6e0dbaSJack F Vogel }
6531b6e0dbaSJack F Vogel 
6541b6e0dbaSJack F Vogel /**
6559ca4041bSJack F Vogel  *  ixgbe_stop_adapter_generic - Generic stop Tx/Rx units
65613705f88SJack F Vogel  *  @hw: pointer to hardware structure
65713705f88SJack F Vogel  *
65813705f88SJack F Vogel  *  Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
65913705f88SJack F Vogel  *  disables transmit and receive units. The adapter_stopped flag is used by
66013705f88SJack F Vogel  *  the shared code and drivers to determine if the adapter is in a stopped
66113705f88SJack F Vogel  *  state and should not touch the hardware.
66213705f88SJack F Vogel  **/
66313705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
66413705f88SJack F Vogel {
66513705f88SJack F Vogel 	u32 number_of_queues;
66613705f88SJack F Vogel 	u32 reg_val;
66713705f88SJack F Vogel 	u16 i;
66813705f88SJack F Vogel 
6692969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_stop_adapter_generic");
6702969bf0eSJack F Vogel 
67113705f88SJack F Vogel 	/*
67213705f88SJack F Vogel 	 * Set the adapter_stopped flag so other driver functions stop touching
67313705f88SJack F Vogel 	 * the hardware
67413705f88SJack F Vogel 	 */
67513705f88SJack F Vogel 	hw->adapter_stopped = TRUE;
67613705f88SJack F Vogel 
67713705f88SJack F Vogel 	/* Disable the receive unit */
67813705f88SJack F Vogel 	reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
67913705f88SJack F Vogel 	reg_val &= ~(IXGBE_RXCTRL_RXEN);
68013705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val);
6819ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
68213705f88SJack F Vogel 	msec_delay(2);
68313705f88SJack F Vogel 
68413705f88SJack F Vogel 	/* Clear interrupt mask to stop from interrupts being generated */
68513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
68613705f88SJack F Vogel 
68713705f88SJack F Vogel 	/* Clear any pending interrupts */
68813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_EICR);
68913705f88SJack F Vogel 
69013705f88SJack F Vogel 	/* Disable the transmit unit.  Each queue must be disabled. */
6919ca4041bSJack F Vogel 	number_of_queues = hw->mac.max_tx_queues;
69213705f88SJack F Vogel 	for (i = 0; i < number_of_queues; i++) {
69313705f88SJack F Vogel 		reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
69413705f88SJack F Vogel 		if (reg_val & IXGBE_TXDCTL_ENABLE) {
69513705f88SJack F Vogel 			reg_val &= ~IXGBE_TXDCTL_ENABLE;
69613705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val);
69713705f88SJack F Vogel 		}
69813705f88SJack F Vogel 	}
69913705f88SJack F Vogel 
7009ca4041bSJack F Vogel 	/*
7019ca4041bSJack F Vogel 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
7029ca4041bSJack F Vogel 	 * access and verify no pending requests
7039ca4041bSJack F Vogel 	 */
704c0014855SJack F Vogel 	ixgbe_disable_pcie_master(hw);
7059ca4041bSJack F Vogel 
70613705f88SJack F Vogel 	return IXGBE_SUCCESS;
70713705f88SJack F Vogel }
70813705f88SJack F Vogel 
70913705f88SJack F Vogel /**
71013705f88SJack F Vogel  *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
71113705f88SJack F Vogel  *  @hw: pointer to hardware structure
71213705f88SJack F Vogel  *  @index: led number to turn on
71313705f88SJack F Vogel  **/
71413705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
71513705f88SJack F Vogel {
71613705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
71713705f88SJack F Vogel 
7182969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_led_on_generic");
7192969bf0eSJack F Vogel 
72013705f88SJack F Vogel 	/* To turn on the LED, set mode to ON. */
72113705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
72213705f88SJack F Vogel 	led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index);
72313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
7249ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
72513705f88SJack F Vogel 
72613705f88SJack F Vogel 	return IXGBE_SUCCESS;
72713705f88SJack F Vogel }
72813705f88SJack F Vogel 
72913705f88SJack F Vogel /**
73013705f88SJack F Vogel  *  ixgbe_led_off_generic - Turns off the software controllable LEDs.
73113705f88SJack F Vogel  *  @hw: pointer to hardware structure
73213705f88SJack F Vogel  *  @index: led number to turn off
73313705f88SJack F Vogel  **/
73413705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
73513705f88SJack F Vogel {
73613705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
73713705f88SJack F Vogel 
7382969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_led_off_generic");
7392969bf0eSJack F Vogel 
74013705f88SJack F Vogel 	/* To turn off the LED, set mode to OFF. */
74113705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
74213705f88SJack F Vogel 	led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index);
74313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
7449ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
74513705f88SJack F Vogel 
74613705f88SJack F Vogel 	return IXGBE_SUCCESS;
74713705f88SJack F Vogel }
74813705f88SJack F Vogel 
74913705f88SJack F Vogel /**
75013705f88SJack F Vogel  *  ixgbe_init_eeprom_params_generic - Initialize EEPROM params
75113705f88SJack F Vogel  *  @hw: pointer to hardware structure
75213705f88SJack F Vogel  *
75313705f88SJack F Vogel  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
75413705f88SJack F Vogel  *  ixgbe_hw struct in order to set up EEPROM access.
75513705f88SJack F Vogel  **/
75613705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
75713705f88SJack F Vogel {
75813705f88SJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
75913705f88SJack F Vogel 	u32 eec;
76013705f88SJack F Vogel 	u16 eeprom_size;
76113705f88SJack F Vogel 
7622969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_eeprom_params_generic");
7632969bf0eSJack F Vogel 
76413705f88SJack F Vogel 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
76513705f88SJack F Vogel 		eeprom->type = ixgbe_eeprom_none;
7665b7f4cedSJack F Vogel 		/* Set default semaphore delay to 10ms which is a well
7675b7f4cedSJack F Vogel 		 * tested value */
7685b7f4cedSJack F Vogel 		eeprom->semaphore_delay = 10;
76913705f88SJack F Vogel 
77013705f88SJack F Vogel 		/*
77113705f88SJack F Vogel 		 * Check for EEPROM present first.
77213705f88SJack F Vogel 		 * If not present leave as none
77313705f88SJack F Vogel 		 */
77413705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
77513705f88SJack F Vogel 		if (eec & IXGBE_EEC_PRES) {
77613705f88SJack F Vogel 			eeprom->type = ixgbe_eeprom_spi;
77713705f88SJack F Vogel 
77813705f88SJack F Vogel 			/*
77913705f88SJack F Vogel 			 * SPI EEPROM is assumed here.  This code would need to
78013705f88SJack F Vogel 			 * change if a future EEPROM is not SPI.
78113705f88SJack F Vogel 			 */
78213705f88SJack F Vogel 			eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
78313705f88SJack F Vogel 			                    IXGBE_EEC_SIZE_SHIFT);
78413705f88SJack F Vogel 			eeprom->word_size = 1 << (eeprom_size +
7852969bf0eSJack F Vogel 			                     IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT);
78613705f88SJack F Vogel 		}
78713705f88SJack F Vogel 
78813705f88SJack F Vogel 		if (eec & IXGBE_EEC_ADDR_SIZE)
78913705f88SJack F Vogel 			eeprom->address_bits = 16;
79013705f88SJack F Vogel 		else
79113705f88SJack F Vogel 			eeprom->address_bits = 8;
79213705f88SJack F Vogel 		DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: "
79313705f88SJack F Vogel 		          "%d\n", eeprom->type, eeprom->word_size,
79413705f88SJack F Vogel 		          eeprom->address_bits);
79513705f88SJack F Vogel 	}
79613705f88SJack F Vogel 
79713705f88SJack F Vogel 	return IXGBE_SUCCESS;
79813705f88SJack F Vogel }
79913705f88SJack F Vogel 
80013705f88SJack F Vogel /**
80113705f88SJack F Vogel  *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
80213705f88SJack F Vogel  *  @hw: pointer to hardware structure
80313705f88SJack F Vogel  *  @offset: offset within the EEPROM to be written to
80413705f88SJack F Vogel  *  @data: 16 bit word to be written to the EEPROM
80513705f88SJack F Vogel  *
80613705f88SJack F Vogel  *  If ixgbe_eeprom_update_checksum is not called after this function, the
80713705f88SJack F Vogel  *  EEPROM will most likely contain an invalid checksum.
80813705f88SJack F Vogel  **/
80913705f88SJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
81013705f88SJack F Vogel {
81113705f88SJack F Vogel 	s32 status;
81213705f88SJack F Vogel 	u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
81313705f88SJack F Vogel 
8142969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_write_eeprom_generic");
8152969bf0eSJack F Vogel 
8169ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
8179ca4041bSJack F Vogel 
8189ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
8199ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
8209ca4041bSJack F Vogel 		goto out;
8219ca4041bSJack F Vogel 	}
8229ca4041bSJack F Vogel 
82313705f88SJack F Vogel 	/* Prepare the EEPROM for writing  */
82413705f88SJack F Vogel 	status = ixgbe_acquire_eeprom(hw);
82513705f88SJack F Vogel 
82613705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
82713705f88SJack F Vogel 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
82813705f88SJack F Vogel 			ixgbe_release_eeprom(hw);
82913705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
83013705f88SJack F Vogel 		}
83113705f88SJack F Vogel 	}
83213705f88SJack F Vogel 
83313705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
83413705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
83513705f88SJack F Vogel 
83613705f88SJack F Vogel 		/*  Send the WRITE ENABLE command (8 bit opcode )  */
83713705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI,
83813705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
83913705f88SJack F Vogel 
84013705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
84113705f88SJack F Vogel 
84213705f88SJack F Vogel 		/*
84313705f88SJack F Vogel 		 * Some SPI eeproms use the 8th address bit embedded in the
84413705f88SJack F Vogel 		 * opcode
84513705f88SJack F Vogel 		 */
84613705f88SJack F Vogel 		if ((hw->eeprom.address_bits == 8) && (offset >= 128))
84713705f88SJack F Vogel 			write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
84813705f88SJack F Vogel 
84913705f88SJack F Vogel 		/* Send the Write command (8-bit opcode + addr) */
85013705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, write_opcode,
85113705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
85213705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
85313705f88SJack F Vogel 		                            hw->eeprom.address_bits);
85413705f88SJack F Vogel 
85513705f88SJack F Vogel 		/* Send the data */
85613705f88SJack F Vogel 		data = (data >> 8) | (data << 8);
85713705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, data, 16);
85813705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
85913705f88SJack F Vogel 
86013705f88SJack F Vogel 		/* Done with writing - release the EEPROM */
86113705f88SJack F Vogel 		ixgbe_release_eeprom(hw);
86213705f88SJack F Vogel 	}
86313705f88SJack F Vogel 
8649ca4041bSJack F Vogel out:
86513705f88SJack F Vogel 	return status;
86613705f88SJack F Vogel }
86713705f88SJack F Vogel 
86813705f88SJack F Vogel /**
86913705f88SJack F Vogel  *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
87013705f88SJack F Vogel  *  @hw: pointer to hardware structure
87113705f88SJack F Vogel  *  @offset: offset within the EEPROM to be read
87213705f88SJack F Vogel  *  @data: read 16 bit value from EEPROM
87313705f88SJack F Vogel  *
87413705f88SJack F Vogel  *  Reads 16 bit value from EEPROM through bit-bang method
87513705f88SJack F Vogel  **/
87613705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
87713705f88SJack F Vogel                                        u16 *data)
87813705f88SJack F Vogel {
87913705f88SJack F Vogel 	s32 status;
88013705f88SJack F Vogel 	u16 word_in;
88113705f88SJack F Vogel 	u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
88213705f88SJack F Vogel 
8832969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic");
8842969bf0eSJack F Vogel 
8859ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
8869ca4041bSJack F Vogel 
8879ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
8889ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
8899ca4041bSJack F Vogel 		goto out;
8909ca4041bSJack F Vogel 	}
8919ca4041bSJack F Vogel 
89213705f88SJack F Vogel 	/* Prepare the EEPROM for reading  */
89313705f88SJack F Vogel 	status = ixgbe_acquire_eeprom(hw);
89413705f88SJack F Vogel 
89513705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
89613705f88SJack F Vogel 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
89713705f88SJack F Vogel 			ixgbe_release_eeprom(hw);
89813705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
89913705f88SJack F Vogel 		}
90013705f88SJack F Vogel 	}
90113705f88SJack F Vogel 
90213705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
90313705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
90413705f88SJack F Vogel 
90513705f88SJack F Vogel 		/*
90613705f88SJack F Vogel 		 * Some SPI eeproms use the 8th address bit embedded in the
90713705f88SJack F Vogel 		 * opcode
90813705f88SJack F Vogel 		 */
90913705f88SJack F Vogel 		if ((hw->eeprom.address_bits == 8) && (offset >= 128))
91013705f88SJack F Vogel 			read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
91113705f88SJack F Vogel 
91213705f88SJack F Vogel 		/* Send the READ command (opcode + addr) */
91313705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, read_opcode,
91413705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
91513705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
91613705f88SJack F Vogel 		                            hw->eeprom.address_bits);
91713705f88SJack F Vogel 
91813705f88SJack F Vogel 		/* Read the data. */
91913705f88SJack F Vogel 		word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
92013705f88SJack F Vogel 		*data = (word_in >> 8) | (word_in << 8);
92113705f88SJack F Vogel 
92213705f88SJack F Vogel 		/* End this read operation */
92313705f88SJack F Vogel 		ixgbe_release_eeprom(hw);
92413705f88SJack F Vogel 	}
92513705f88SJack F Vogel 
9269ca4041bSJack F Vogel out:
92713705f88SJack F Vogel 	return status;
92813705f88SJack F Vogel }
92913705f88SJack F Vogel 
93013705f88SJack F Vogel /**
9312969bf0eSJack F Vogel  *  ixgbe_read_eerd_generic - Read EEPROM word using EERD
93213705f88SJack F Vogel  *  @hw: pointer to hardware structure
93313705f88SJack F Vogel  *  @offset: offset of  word in the EEPROM to read
93413705f88SJack F Vogel  *  @data: word read from the EEPROM
93513705f88SJack F Vogel  *
93613705f88SJack F Vogel  *  Reads a 16 bit word from the EEPROM using the EERD register.
93713705f88SJack F Vogel  **/
9382969bf0eSJack F Vogel s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
93913705f88SJack F Vogel {
94013705f88SJack F Vogel 	u32 eerd;
94113705f88SJack F Vogel 	s32 status;
94213705f88SJack F Vogel 
9432969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_read_eerd_generic");
9442969bf0eSJack F Vogel 
9459ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
9469ca4041bSJack F Vogel 
9479ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
9489ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
9499ca4041bSJack F Vogel 		goto out;
9509ca4041bSJack F Vogel 	}
9519ca4041bSJack F Vogel 
9522969bf0eSJack F Vogel 	eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) +
9532969bf0eSJack F Vogel 	       IXGBE_EEPROM_RW_REG_START;
95413705f88SJack F Vogel 
95513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
9562969bf0eSJack F Vogel 	status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
95713705f88SJack F Vogel 
95813705f88SJack F Vogel 	if (status == IXGBE_SUCCESS)
95913705f88SJack F Vogel 		*data = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
9602969bf0eSJack F Vogel 		         IXGBE_EEPROM_RW_REG_DATA);
96113705f88SJack F Vogel 	else
96213705f88SJack F Vogel 		DEBUGOUT("Eeprom read timed out\n");
96313705f88SJack F Vogel 
9649ca4041bSJack F Vogel out:
96513705f88SJack F Vogel 	return status;
96613705f88SJack F Vogel }
96713705f88SJack F Vogel 
96813705f88SJack F Vogel /**
969*1a4e3449SJack F Vogel  *  ixgbe_write_eewr_generic - Write EEPROM word using EEWR
970*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
971*1a4e3449SJack F Vogel  *  @offset: offset of  word in the EEPROM to write
972*1a4e3449SJack F Vogel  *  @data: word write to the EEPROM
973*1a4e3449SJack F Vogel  *
974*1a4e3449SJack F Vogel  *  Write a 16 bit word to the EEPROM using the EEWR register.
975*1a4e3449SJack F Vogel  **/
976*1a4e3449SJack F Vogel s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
977*1a4e3449SJack F Vogel {
978*1a4e3449SJack F Vogel 	u32 eewr;
979*1a4e3449SJack F Vogel 	s32 status;
980*1a4e3449SJack F Vogel 
981*1a4e3449SJack F Vogel 	DEBUGFUNC("ixgbe_write_eewr_generic");
982*1a4e3449SJack F Vogel 
983*1a4e3449SJack F Vogel 	hw->eeprom.ops.init_params(hw);
984*1a4e3449SJack F Vogel 
985*1a4e3449SJack F Vogel 	if (offset >= hw->eeprom.word_size) {
986*1a4e3449SJack F Vogel 		status = IXGBE_ERR_EEPROM;
987*1a4e3449SJack F Vogel 		goto out;
988*1a4e3449SJack F Vogel 	}
989*1a4e3449SJack F Vogel 
990*1a4e3449SJack F Vogel 	eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) |
991*1a4e3449SJack F Vogel 	       (data << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START;
992*1a4e3449SJack F Vogel 
993*1a4e3449SJack F Vogel 	status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
994*1a4e3449SJack F Vogel 	if (status != IXGBE_SUCCESS) {
995*1a4e3449SJack F Vogel 		DEBUGOUT("Eeprom write EEWR timed out\n");
996*1a4e3449SJack F Vogel 		goto out;
997*1a4e3449SJack F Vogel 	}
998*1a4e3449SJack F Vogel 
999*1a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
1000*1a4e3449SJack F Vogel 
1001*1a4e3449SJack F Vogel 	status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
1002*1a4e3449SJack F Vogel 	if (status != IXGBE_SUCCESS) {
1003*1a4e3449SJack F Vogel 		DEBUGOUT("Eeprom write EEWR timed out\n");
1004*1a4e3449SJack F Vogel 		goto out;
1005*1a4e3449SJack F Vogel 	}
1006*1a4e3449SJack F Vogel 
1007*1a4e3449SJack F Vogel out:
1008*1a4e3449SJack F Vogel 	return status;
1009*1a4e3449SJack F Vogel }
1010*1a4e3449SJack F Vogel 
1011*1a4e3449SJack F Vogel /**
10122969bf0eSJack F Vogel  *  ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
101313705f88SJack F Vogel  *  @hw: pointer to hardware structure
10142969bf0eSJack F Vogel  *  @ee_reg: EEPROM flag for polling
101513705f88SJack F Vogel  *
10162969bf0eSJack F Vogel  *  Polls the status bit (bit 1) of the EERD or EEWR to determine when the
10172969bf0eSJack F Vogel  *  read or write is done respectively.
101813705f88SJack F Vogel  **/
10192969bf0eSJack F Vogel s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
102013705f88SJack F Vogel {
102113705f88SJack F Vogel 	u32 i;
102213705f88SJack F Vogel 	u32 reg;
102313705f88SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM;
102413705f88SJack F Vogel 
10252969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_poll_eerd_eewr_done");
10262969bf0eSJack F Vogel 
10272969bf0eSJack F Vogel 	for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) {
10282969bf0eSJack F Vogel 		if (ee_reg == IXGBE_NVM_POLL_READ)
102913705f88SJack F Vogel 			reg = IXGBE_READ_REG(hw, IXGBE_EERD);
10302969bf0eSJack F Vogel 		else
10312969bf0eSJack F Vogel 			reg = IXGBE_READ_REG(hw, IXGBE_EEWR);
10322969bf0eSJack F Vogel 
10332969bf0eSJack F Vogel 		if (reg & IXGBE_EEPROM_RW_REG_DONE) {
103413705f88SJack F Vogel 			status = IXGBE_SUCCESS;
103513705f88SJack F Vogel 			break;
103613705f88SJack F Vogel 		}
103713705f88SJack F Vogel 		usec_delay(5);
103813705f88SJack F Vogel 	}
103913705f88SJack F Vogel 	return status;
104013705f88SJack F Vogel }
104113705f88SJack F Vogel 
104213705f88SJack F Vogel /**
104313705f88SJack F Vogel  *  ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang
104413705f88SJack F Vogel  *  @hw: pointer to hardware structure
104513705f88SJack F Vogel  *
104613705f88SJack F Vogel  *  Prepares EEPROM for access using bit-bang method. This function should
104713705f88SJack F Vogel  *  be called before issuing a command to the EEPROM.
104813705f88SJack F Vogel  **/
104913705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
105013705f88SJack F Vogel {
105113705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
105213705f88SJack F Vogel 	u32 eec;
105313705f88SJack F Vogel 	u32 i;
105413705f88SJack F Vogel 
10552969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_acquire_eeprom");
10562969bf0eSJack F Vogel 
105713705f88SJack F Vogel 	if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS)
105813705f88SJack F Vogel 		status = IXGBE_ERR_SWFW_SYNC;
105913705f88SJack F Vogel 
106013705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
106113705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
106213705f88SJack F Vogel 
106313705f88SJack F Vogel 		/* Request EEPROM Access */
106413705f88SJack F Vogel 		eec |= IXGBE_EEC_REQ;
106513705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
106613705f88SJack F Vogel 
106713705f88SJack F Vogel 		for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
106813705f88SJack F Vogel 			eec = IXGBE_READ_REG(hw, IXGBE_EEC);
106913705f88SJack F Vogel 			if (eec & IXGBE_EEC_GNT)
107013705f88SJack F Vogel 				break;
107113705f88SJack F Vogel 			usec_delay(5);
107213705f88SJack F Vogel 		}
107313705f88SJack F Vogel 
10749ca4041bSJack F Vogel 		/* Release if grant not acquired */
107513705f88SJack F Vogel 		if (!(eec & IXGBE_EEC_GNT)) {
107613705f88SJack F Vogel 			eec &= ~IXGBE_EEC_REQ;
107713705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
107813705f88SJack F Vogel 			DEBUGOUT("Could not acquire EEPROM grant\n");
107913705f88SJack F Vogel 
108013705f88SJack F Vogel 			ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
108113705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
108213705f88SJack F Vogel 		}
108313705f88SJack F Vogel 
108413705f88SJack F Vogel 		/* Setup EEPROM for Read/Write */
108513705f88SJack F Vogel 		if (status == IXGBE_SUCCESS) {
108613705f88SJack F Vogel 			/* Clear CS and SK */
108713705f88SJack F Vogel 			eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
108813705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
108913705f88SJack F Vogel 			IXGBE_WRITE_FLUSH(hw);
109013705f88SJack F Vogel 			usec_delay(1);
109113705f88SJack F Vogel 		}
1092*1a4e3449SJack F Vogel 	}
109313705f88SJack F Vogel 	return status;
109413705f88SJack F Vogel }
109513705f88SJack F Vogel 
109613705f88SJack F Vogel /**
109713705f88SJack F Vogel  *  ixgbe_get_eeprom_semaphore - Get hardware semaphore
109813705f88SJack F Vogel  *  @hw: pointer to hardware structure
109913705f88SJack F Vogel  *
110013705f88SJack F Vogel  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
110113705f88SJack F Vogel  **/
110213705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
110313705f88SJack F Vogel {
110413705f88SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM;
1105d8602bb9SJack F Vogel 	u32 timeout = 2000;
110613705f88SJack F Vogel 	u32 i;
110713705f88SJack F Vogel 	u32 swsm;
110813705f88SJack F Vogel 
11092969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_eeprom_semaphore");
11102969bf0eSJack F Vogel 
1111*1a4e3449SJack F Vogel 
111213705f88SJack F Vogel 	/* Get SMBI software semaphore between device drivers first */
111313705f88SJack F Vogel 	for (i = 0; i < timeout; i++) {
111413705f88SJack F Vogel 		/*
111513705f88SJack F Vogel 		 * If the SMBI bit is 0 when we read it, then the bit will be
111613705f88SJack F Vogel 		 * set and we have the semaphore
111713705f88SJack F Vogel 		 */
111813705f88SJack F Vogel 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
111913705f88SJack F Vogel 		if (!(swsm & IXGBE_SWSM_SMBI)) {
112013705f88SJack F Vogel 			status = IXGBE_SUCCESS;
112113705f88SJack F Vogel 			break;
112213705f88SJack F Vogel 		}
11230ac6dfecSJack F Vogel 		usec_delay(50);
112413705f88SJack F Vogel 	}
112513705f88SJack F Vogel 
112613705f88SJack F Vogel 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
112713705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
112813705f88SJack F Vogel 		for (i = 0; i < timeout; i++) {
112913705f88SJack F Vogel 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
113013705f88SJack F Vogel 
113113705f88SJack F Vogel 			/* Set the SW EEPROM semaphore bit to request access */
113213705f88SJack F Vogel 			swsm |= IXGBE_SWSM_SWESMBI;
113313705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
113413705f88SJack F Vogel 
113513705f88SJack F Vogel 			/*
113613705f88SJack F Vogel 			 * If we set the bit successfully then we got the
113713705f88SJack F Vogel 			 * semaphore.
113813705f88SJack F Vogel 			 */
113913705f88SJack F Vogel 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
114013705f88SJack F Vogel 			if (swsm & IXGBE_SWSM_SWESMBI)
114113705f88SJack F Vogel 				break;
114213705f88SJack F Vogel 
114313705f88SJack F Vogel 			usec_delay(50);
114413705f88SJack F Vogel 		}
114513705f88SJack F Vogel 
114613705f88SJack F Vogel 		/*
114713705f88SJack F Vogel 		 * Release semaphores and return error if SW EEPROM semaphore
114813705f88SJack F Vogel 		 * was not granted because we don't have access to the EEPROM
114913705f88SJack F Vogel 		 */
115013705f88SJack F Vogel 		if (i >= timeout) {
11510ac6dfecSJack F Vogel 			DEBUGOUT("SWESMBI Software EEPROM semaphore "
115213705f88SJack F Vogel 			         "not granted.\n");
115313705f88SJack F Vogel 			ixgbe_release_eeprom_semaphore(hw);
115413705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
115513705f88SJack F Vogel 		}
11560ac6dfecSJack F Vogel 	} else {
11570ac6dfecSJack F Vogel 		DEBUGOUT("Software semaphore SMBI between device drivers "
11580ac6dfecSJack F Vogel 		         "not granted.\n");
115913705f88SJack F Vogel 	}
116013705f88SJack F Vogel 
116113705f88SJack F Vogel 	return status;
116213705f88SJack F Vogel }
116313705f88SJack F Vogel 
116413705f88SJack F Vogel /**
116513705f88SJack F Vogel  *  ixgbe_release_eeprom_semaphore - Release hardware semaphore
116613705f88SJack F Vogel  *  @hw: pointer to hardware structure
116713705f88SJack F Vogel  *
116813705f88SJack F Vogel  *  This function clears hardware semaphore bits.
116913705f88SJack F Vogel  **/
117013705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
117113705f88SJack F Vogel {
117213705f88SJack F Vogel 	u32 swsm;
117313705f88SJack F Vogel 
11742969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_release_eeprom_semaphore");
11752969bf0eSJack F Vogel 
117613705f88SJack F Vogel 	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
117713705f88SJack F Vogel 
117813705f88SJack F Vogel 	/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
117913705f88SJack F Vogel 	swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI);
118013705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
11819ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
118213705f88SJack F Vogel }
118313705f88SJack F Vogel 
118413705f88SJack F Vogel /**
118513705f88SJack F Vogel  *  ixgbe_ready_eeprom - Polls for EEPROM ready
118613705f88SJack F Vogel  *  @hw: pointer to hardware structure
118713705f88SJack F Vogel  **/
118813705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
118913705f88SJack F Vogel {
119013705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
119113705f88SJack F Vogel 	u16 i;
119213705f88SJack F Vogel 	u8 spi_stat_reg;
119313705f88SJack F Vogel 
11942969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_ready_eeprom");
11952969bf0eSJack F Vogel 
119613705f88SJack F Vogel 	/*
119713705f88SJack F Vogel 	 * Read "Status Register" repeatedly until the LSB is cleared.  The
119813705f88SJack F Vogel 	 * EEPROM will signal that the command has been completed by clearing
119913705f88SJack F Vogel 	 * bit 0 of the internal status register.  If it's not cleared within
120013705f88SJack F Vogel 	 * 5 milliseconds, then error out.
120113705f88SJack F Vogel 	 */
120213705f88SJack F Vogel 	for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) {
120313705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI,
120413705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
120513705f88SJack F Vogel 		spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8);
120613705f88SJack F Vogel 		if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI))
120713705f88SJack F Vogel 			break;
120813705f88SJack F Vogel 
120913705f88SJack F Vogel 		usec_delay(5);
121013705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
121113705f88SJack F Vogel 	};
121213705f88SJack F Vogel 
121313705f88SJack F Vogel 	/*
121413705f88SJack F Vogel 	 * On some parts, SPI write time could vary from 0-20mSec on 3.3V
121513705f88SJack F Vogel 	 * devices (and only 0-5mSec on 5V devices)
121613705f88SJack F Vogel 	 */
121713705f88SJack F Vogel 	if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
121813705f88SJack F Vogel 		DEBUGOUT("SPI EEPROM Status error\n");
121913705f88SJack F Vogel 		status = IXGBE_ERR_EEPROM;
122013705f88SJack F Vogel 	}
122113705f88SJack F Vogel 
122213705f88SJack F Vogel 	return status;
122313705f88SJack F Vogel }
122413705f88SJack F Vogel 
122513705f88SJack F Vogel /**
122613705f88SJack F Vogel  *  ixgbe_standby_eeprom - Returns EEPROM to a "standby" state
122713705f88SJack F Vogel  *  @hw: pointer to hardware structure
122813705f88SJack F Vogel  **/
122913705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
123013705f88SJack F Vogel {
123113705f88SJack F Vogel 	u32 eec;
123213705f88SJack F Vogel 
12332969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_standby_eeprom");
12342969bf0eSJack F Vogel 
123513705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
123613705f88SJack F Vogel 
123713705f88SJack F Vogel 	/* Toggle CS to flush commands */
123813705f88SJack F Vogel 	eec |= IXGBE_EEC_CS;
123913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
124013705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
124113705f88SJack F Vogel 	usec_delay(1);
124213705f88SJack F Vogel 	eec &= ~IXGBE_EEC_CS;
124313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
124413705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
124513705f88SJack F Vogel 	usec_delay(1);
124613705f88SJack F Vogel }
124713705f88SJack F Vogel 
124813705f88SJack F Vogel /**
124913705f88SJack F Vogel  *  ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM.
125013705f88SJack F Vogel  *  @hw: pointer to hardware structure
125113705f88SJack F Vogel  *  @data: data to send to the EEPROM
125213705f88SJack F Vogel  *  @count: number of bits to shift out
125313705f88SJack F Vogel  **/
125413705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
125513705f88SJack F Vogel                                         u16 count)
125613705f88SJack F Vogel {
125713705f88SJack F Vogel 	u32 eec;
125813705f88SJack F Vogel 	u32 mask;
125913705f88SJack F Vogel 	u32 i;
126013705f88SJack F Vogel 
12612969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_shift_out_eeprom_bits");
12622969bf0eSJack F Vogel 
126313705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
126413705f88SJack F Vogel 
126513705f88SJack F Vogel 	/*
126613705f88SJack F Vogel 	 * Mask is used to shift "count" bits of "data" out to the EEPROM
126713705f88SJack F Vogel 	 * one bit at a time.  Determine the starting bit based on count
126813705f88SJack F Vogel 	 */
126913705f88SJack F Vogel 	mask = 0x01 << (count - 1);
127013705f88SJack F Vogel 
127113705f88SJack F Vogel 	for (i = 0; i < count; i++) {
127213705f88SJack F Vogel 		/*
127313705f88SJack F Vogel 		 * A "1" is shifted out to the EEPROM by setting bit "DI" to a
127413705f88SJack F Vogel 		 * "1", and then raising and then lowering the clock (the SK
127513705f88SJack F Vogel 		 * bit controls the clock input to the EEPROM).  A "0" is
127613705f88SJack F Vogel 		 * shifted out to the EEPROM by setting "DI" to "0" and then
127713705f88SJack F Vogel 		 * raising and then lowering the clock.
127813705f88SJack F Vogel 		 */
127913705f88SJack F Vogel 		if (data & mask)
128013705f88SJack F Vogel 			eec |= IXGBE_EEC_DI;
128113705f88SJack F Vogel 		else
128213705f88SJack F Vogel 			eec &= ~IXGBE_EEC_DI;
128313705f88SJack F Vogel 
128413705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
128513705f88SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
128613705f88SJack F Vogel 
128713705f88SJack F Vogel 		usec_delay(1);
128813705f88SJack F Vogel 
128913705f88SJack F Vogel 		ixgbe_raise_eeprom_clk(hw, &eec);
129013705f88SJack F Vogel 		ixgbe_lower_eeprom_clk(hw, &eec);
129113705f88SJack F Vogel 
129213705f88SJack F Vogel 		/*
129313705f88SJack F Vogel 		 * Shift mask to signify next bit of data to shift in to the
129413705f88SJack F Vogel 		 * EEPROM
129513705f88SJack F Vogel 		 */
129613705f88SJack F Vogel 		mask = mask >> 1;
129713705f88SJack F Vogel 	};
129813705f88SJack F Vogel 
129913705f88SJack F Vogel 	/* We leave the "DI" bit set to "0" when we leave this routine. */
130013705f88SJack F Vogel 	eec &= ~IXGBE_EEC_DI;
130113705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
130213705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
130313705f88SJack F Vogel }
130413705f88SJack F Vogel 
130513705f88SJack F Vogel /**
130613705f88SJack F Vogel  *  ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
130713705f88SJack F Vogel  *  @hw: pointer to hardware structure
130813705f88SJack F Vogel  **/
130913705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
131013705f88SJack F Vogel {
131113705f88SJack F Vogel 	u32 eec;
131213705f88SJack F Vogel 	u32 i;
131313705f88SJack F Vogel 	u16 data = 0;
131413705f88SJack F Vogel 
13152969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_shift_in_eeprom_bits");
13162969bf0eSJack F Vogel 
131713705f88SJack F Vogel 	/*
131813705f88SJack F Vogel 	 * In order to read a register from the EEPROM, we need to shift
131913705f88SJack F Vogel 	 * 'count' bits in from the EEPROM. Bits are "shifted in" by raising
132013705f88SJack F Vogel 	 * the clock input to the EEPROM (setting the SK bit), and then reading
132113705f88SJack F Vogel 	 * the value of the "DO" bit.  During this "shifting in" process the
132213705f88SJack F Vogel 	 * "DI" bit should always be clear.
132313705f88SJack F Vogel 	 */
132413705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
132513705f88SJack F Vogel 
132613705f88SJack F Vogel 	eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
132713705f88SJack F Vogel 
132813705f88SJack F Vogel 	for (i = 0; i < count; i++) {
132913705f88SJack F Vogel 		data = data << 1;
133013705f88SJack F Vogel 		ixgbe_raise_eeprom_clk(hw, &eec);
133113705f88SJack F Vogel 
133213705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
133313705f88SJack F Vogel 
133413705f88SJack F Vogel 		eec &= ~(IXGBE_EEC_DI);
133513705f88SJack F Vogel 		if (eec & IXGBE_EEC_DO)
133613705f88SJack F Vogel 			data |= 1;
133713705f88SJack F Vogel 
133813705f88SJack F Vogel 		ixgbe_lower_eeprom_clk(hw, &eec);
133913705f88SJack F Vogel 	}
134013705f88SJack F Vogel 
134113705f88SJack F Vogel 	return data;
134213705f88SJack F Vogel }
134313705f88SJack F Vogel 
134413705f88SJack F Vogel /**
134513705f88SJack F Vogel  *  ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input.
134613705f88SJack F Vogel  *  @hw: pointer to hardware structure
134713705f88SJack F Vogel  *  @eec: EEC register's current value
134813705f88SJack F Vogel  **/
134913705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
135013705f88SJack F Vogel {
13512969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_raise_eeprom_clk");
13522969bf0eSJack F Vogel 
135313705f88SJack F Vogel 	/*
135413705f88SJack F Vogel 	 * Raise the clock input to the EEPROM
135513705f88SJack F Vogel 	 * (setting the SK bit), then delay
135613705f88SJack F Vogel 	 */
135713705f88SJack F Vogel 	*eec = *eec | IXGBE_EEC_SK;
135813705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
135913705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
136013705f88SJack F Vogel 	usec_delay(1);
136113705f88SJack F Vogel }
136213705f88SJack F Vogel 
136313705f88SJack F Vogel /**
136413705f88SJack F Vogel  *  ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input.
136513705f88SJack F Vogel  *  @hw: pointer to hardware structure
136613705f88SJack F Vogel  *  @eecd: EECD's current value
136713705f88SJack F Vogel  **/
136813705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
136913705f88SJack F Vogel {
13702969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_lower_eeprom_clk");
13712969bf0eSJack F Vogel 
137213705f88SJack F Vogel 	/*
137313705f88SJack F Vogel 	 * Lower the clock input to the EEPROM (clearing the SK bit), then
137413705f88SJack F Vogel 	 * delay
137513705f88SJack F Vogel 	 */
137613705f88SJack F Vogel 	*eec = *eec & ~IXGBE_EEC_SK;
137713705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
137813705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
137913705f88SJack F Vogel 	usec_delay(1);
138013705f88SJack F Vogel }
138113705f88SJack F Vogel 
138213705f88SJack F Vogel /**
138313705f88SJack F Vogel  *  ixgbe_release_eeprom - Release EEPROM, release semaphores
138413705f88SJack F Vogel  *  @hw: pointer to hardware structure
138513705f88SJack F Vogel  **/
138613705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
138713705f88SJack F Vogel {
138813705f88SJack F Vogel 	u32 eec;
138913705f88SJack F Vogel 
13902969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_release_eeprom");
13912969bf0eSJack F Vogel 
139213705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
139313705f88SJack F Vogel 
139413705f88SJack F Vogel 	eec |= IXGBE_EEC_CS;  /* Pull CS high */
139513705f88SJack F Vogel 	eec &= ~IXGBE_EEC_SK; /* Lower SCK */
139613705f88SJack F Vogel 
139713705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
139813705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
139913705f88SJack F Vogel 
140013705f88SJack F Vogel 	usec_delay(1);
140113705f88SJack F Vogel 
140213705f88SJack F Vogel 	/* Stop requesting EEPROM access */
140313705f88SJack F Vogel 	eec &= ~IXGBE_EEC_REQ;
140413705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
140513705f88SJack F Vogel 
140613705f88SJack F Vogel 	ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
1407d8602bb9SJack F Vogel 
1408d8602bb9SJack F Vogel 	/* Delay before attempt to obtain semaphore again to allow FW access */
1409d8602bb9SJack F Vogel 	msec_delay(hw->eeprom.semaphore_delay);
141013705f88SJack F Vogel }
141113705f88SJack F Vogel 
141213705f88SJack F Vogel /**
14132969bf0eSJack F Vogel  *  ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
141413705f88SJack F Vogel  *  @hw: pointer to hardware structure
141513705f88SJack F Vogel  **/
14162969bf0eSJack F Vogel u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
141713705f88SJack F Vogel {
141813705f88SJack F Vogel 	u16 i;
141913705f88SJack F Vogel 	u16 j;
142013705f88SJack F Vogel 	u16 checksum = 0;
142113705f88SJack F Vogel 	u16 length = 0;
142213705f88SJack F Vogel 	u16 pointer = 0;
142313705f88SJack F Vogel 	u16 word = 0;
142413705f88SJack F Vogel 
14252969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic");
14262969bf0eSJack F Vogel 
142713705f88SJack F Vogel 	/* Include 0x0-0x3F in the checksum */
142813705f88SJack F Vogel 	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
14299ca4041bSJack F Vogel 		if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) {
143013705f88SJack F Vogel 			DEBUGOUT("EEPROM read failed\n");
143113705f88SJack F Vogel 			break;
143213705f88SJack F Vogel 		}
143313705f88SJack F Vogel 		checksum += word;
143413705f88SJack F Vogel 	}
143513705f88SJack F Vogel 
143613705f88SJack F Vogel 	/* Include all data from pointers except for the fw pointer */
143713705f88SJack F Vogel 	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
14389ca4041bSJack F Vogel 		hw->eeprom.ops.read(hw, i, &pointer);
143913705f88SJack F Vogel 
144013705f88SJack F Vogel 		/* Make sure the pointer seems valid */
144113705f88SJack F Vogel 		if (pointer != 0xFFFF && pointer != 0) {
14429ca4041bSJack F Vogel 			hw->eeprom.ops.read(hw, pointer, &length);
144313705f88SJack F Vogel 
144413705f88SJack F Vogel 			if (length != 0xFFFF && length != 0) {
144513705f88SJack F Vogel 				for (j = pointer+1; j <= pointer+length; j++) {
14469ca4041bSJack F Vogel 					hw->eeprom.ops.read(hw, j, &word);
144713705f88SJack F Vogel 					checksum += word;
144813705f88SJack F Vogel 				}
144913705f88SJack F Vogel 			}
145013705f88SJack F Vogel 		}
145113705f88SJack F Vogel 	}
145213705f88SJack F Vogel 
145313705f88SJack F Vogel 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
145413705f88SJack F Vogel 
145513705f88SJack F Vogel 	return checksum;
145613705f88SJack F Vogel }
145713705f88SJack F Vogel 
145813705f88SJack F Vogel /**
145913705f88SJack F Vogel  *  ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
146013705f88SJack F Vogel  *  @hw: pointer to hardware structure
146113705f88SJack F Vogel  *  @checksum_val: calculated checksum
146213705f88SJack F Vogel  *
146313705f88SJack F Vogel  *  Performs checksum calculation and validates the EEPROM checksum.  If the
146413705f88SJack F Vogel  *  caller does not need checksum_val, the value can be NULL.
146513705f88SJack F Vogel  **/
146613705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
146713705f88SJack F Vogel                                            u16 *checksum_val)
146813705f88SJack F Vogel {
146913705f88SJack F Vogel 	s32 status;
147013705f88SJack F Vogel 	u16 checksum;
147113705f88SJack F Vogel 	u16 read_checksum = 0;
147213705f88SJack F Vogel 
14732969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic");
14742969bf0eSJack F Vogel 
147513705f88SJack F Vogel 	/*
147613705f88SJack F Vogel 	 * Read the first word from the EEPROM. If this times out or fails, do
147713705f88SJack F Vogel 	 * not continue or we could be in for a very long wait while every
147813705f88SJack F Vogel 	 * EEPROM read fails
147913705f88SJack F Vogel 	 */
14809ca4041bSJack F Vogel 	status = hw->eeprom.ops.read(hw, 0, &checksum);
148113705f88SJack F Vogel 
148213705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
14832969bf0eSJack F Vogel 		checksum = hw->eeprom.ops.calc_checksum(hw);
148413705f88SJack F Vogel 
14859ca4041bSJack F Vogel 		hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
148613705f88SJack F Vogel 
148713705f88SJack F Vogel 		/*
148813705f88SJack F Vogel 		 * Verify read checksum from EEPROM is the same as
148913705f88SJack F Vogel 		 * calculated checksum
149013705f88SJack F Vogel 		 */
14919ca4041bSJack F Vogel 		if (read_checksum != checksum)
149213705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM_CHECKSUM;
149313705f88SJack F Vogel 
149413705f88SJack F Vogel 		/* If the user cares, return the calculated checksum */
14959ca4041bSJack F Vogel 		if (checksum_val)
149613705f88SJack F Vogel 			*checksum_val = checksum;
149713705f88SJack F Vogel 	} else {
149813705f88SJack F Vogel 		DEBUGOUT("EEPROM read failed\n");
149913705f88SJack F Vogel 	}
150013705f88SJack F Vogel 
150113705f88SJack F Vogel 	return status;
150213705f88SJack F Vogel }
150313705f88SJack F Vogel 
150413705f88SJack F Vogel /**
15059ca4041bSJack F Vogel  *  ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum
150613705f88SJack F Vogel  *  @hw: pointer to hardware structure
150713705f88SJack F Vogel  **/
150813705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
150913705f88SJack F Vogel {
151013705f88SJack F Vogel 	s32 status;
151113705f88SJack F Vogel 	u16 checksum;
151213705f88SJack F Vogel 
15132969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_update_eeprom_checksum_generic");
15142969bf0eSJack F Vogel 
151513705f88SJack F Vogel 	/*
151613705f88SJack F Vogel 	 * Read the first word from the EEPROM. If this times out or fails, do
151713705f88SJack F Vogel 	 * not continue or we could be in for a very long wait while every
151813705f88SJack F Vogel 	 * EEPROM read fails
151913705f88SJack F Vogel 	 */
15209ca4041bSJack F Vogel 	status = hw->eeprom.ops.read(hw, 0, &checksum);
152113705f88SJack F Vogel 
152213705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
15232969bf0eSJack F Vogel 		checksum = hw->eeprom.ops.calc_checksum(hw);
15249ca4041bSJack F Vogel 		status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
152513705f88SJack F Vogel 		                              checksum);
152613705f88SJack F Vogel 	} else {
152713705f88SJack F Vogel 		DEBUGOUT("EEPROM read failed\n");
152813705f88SJack F Vogel 	}
152913705f88SJack F Vogel 
153013705f88SJack F Vogel 	return status;
153113705f88SJack F Vogel }
153213705f88SJack F Vogel 
153313705f88SJack F Vogel /**
153413705f88SJack F Vogel  *  ixgbe_validate_mac_addr - Validate MAC address
153513705f88SJack F Vogel  *  @mac_addr: pointer to MAC address.
153613705f88SJack F Vogel  *
153713705f88SJack F Vogel  *  Tests a MAC address to ensure it is a valid Individual Address
153813705f88SJack F Vogel  **/
153913705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr)
154013705f88SJack F Vogel {
154113705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
154213705f88SJack F Vogel 
15432969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_validate_mac_addr");
15442969bf0eSJack F Vogel 
154513705f88SJack F Vogel 	/* Make sure it is not a multicast address */
154613705f88SJack F Vogel 	if (IXGBE_IS_MULTICAST(mac_addr)) {
154713705f88SJack F Vogel 		DEBUGOUT("MAC address is multicast\n");
154813705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
154913705f88SJack F Vogel 	/* Not a broadcast address */
155013705f88SJack F Vogel 	} else if (IXGBE_IS_BROADCAST(mac_addr)) {
155113705f88SJack F Vogel 		DEBUGOUT("MAC address is broadcast\n");
155213705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
155313705f88SJack F Vogel 	/* Reject the zero address */
155413705f88SJack F Vogel 	} else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
155513705f88SJack F Vogel 	           mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
155613705f88SJack F Vogel 		DEBUGOUT("MAC address is all zeros\n");
155713705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
155813705f88SJack F Vogel 	}
155913705f88SJack F Vogel 	return status;
156013705f88SJack F Vogel }
156113705f88SJack F Vogel 
156213705f88SJack F Vogel /**
15639ca4041bSJack F Vogel  *  ixgbe_set_rar_generic - Set Rx address register
156413705f88SJack F Vogel  *  @hw: pointer to hardware structure
156513705f88SJack F Vogel  *  @index: Receive address register to write
15669ca4041bSJack F Vogel  *  @addr: Address to put into receive address register
15679ca4041bSJack F Vogel  *  @vmdq: VMDq "set" or "pool" index
156813705f88SJack F Vogel  *  @enable_addr: set flag that address is active
156913705f88SJack F Vogel  *
157013705f88SJack F Vogel  *  Puts an ethernet address into a receive address register.
157113705f88SJack F Vogel  **/
15729ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
157313705f88SJack F Vogel                           u32 enable_addr)
157413705f88SJack F Vogel {
157513705f88SJack F Vogel 	u32 rar_low, rar_high;
15769ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
157713705f88SJack F Vogel 
15782969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_rar_generic");
15792969bf0eSJack F Vogel 
1580*1a4e3449SJack F Vogel 	/* Make sure we are using a valid rar index range */
1581*1a4e3449SJack F Vogel 	if (index >= rar_entries) {
1582*1a4e3449SJack F Vogel 		DEBUGOUT1("RAR index %d is out of range.\n", index);
1583*1a4e3449SJack F Vogel 		return IXGBE_ERR_INVALID_ARGUMENT;
1584*1a4e3449SJack F Vogel 	}
1585*1a4e3449SJack F Vogel 
15869ca4041bSJack F Vogel 	/* setup VMDq pool selection before this RAR gets enabled */
15879ca4041bSJack F Vogel 	hw->mac.ops.set_vmdq(hw, index, vmdq);
15889ca4041bSJack F Vogel 
158913705f88SJack F Vogel 	/*
15909ca4041bSJack F Vogel 	 * HW expects these in little endian so we reverse the byte
15919ca4041bSJack F Vogel 	 * order from network order (big endian) to little endian
159213705f88SJack F Vogel 	 */
159313705f88SJack F Vogel 	rar_low = ((u32)addr[0] |
159413705f88SJack F Vogel 	           ((u32)addr[1] << 8) |
159513705f88SJack F Vogel 	           ((u32)addr[2] << 16) |
159613705f88SJack F Vogel 	           ((u32)addr[3] << 24));
15979ca4041bSJack F Vogel 	/*
15989ca4041bSJack F Vogel 	 * Some parts put the VMDq setting in the extra RAH bits,
15999ca4041bSJack F Vogel 	 * so save everything except the lower 16 bits that hold part
16009ca4041bSJack F Vogel 	 * of the address and the address valid bit.
16019ca4041bSJack F Vogel 	 */
16029ca4041bSJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
16039ca4041bSJack F Vogel 	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
16049ca4041bSJack F Vogel 	rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
160513705f88SJack F Vogel 
160613705f88SJack F Vogel 	if (enable_addr != 0)
160713705f88SJack F Vogel 		rar_high |= IXGBE_RAH_AV;
160813705f88SJack F Vogel 
160913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
161013705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
161113705f88SJack F Vogel 
161213705f88SJack F Vogel 	return IXGBE_SUCCESS;
161313705f88SJack F Vogel }
161413705f88SJack F Vogel 
161513705f88SJack F Vogel /**
16165b7f4cedSJack F Vogel  *  ixgbe_clear_rar_generic - Remove Rx address register
16175b7f4cedSJack F Vogel  *  @hw: pointer to hardware structure
16185b7f4cedSJack F Vogel  *  @index: Receive address register to write
16195b7f4cedSJack F Vogel  *
16205b7f4cedSJack F Vogel  *  Clears an ethernet address from a receive address register.
16215b7f4cedSJack F Vogel  **/
16225b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
16235b7f4cedSJack F Vogel {
16245b7f4cedSJack F Vogel 	u32 rar_high;
16255b7f4cedSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
16265b7f4cedSJack F Vogel 
16272969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_clear_rar_generic");
16282969bf0eSJack F Vogel 
16295b7f4cedSJack F Vogel 	/* Make sure we are using a valid rar index range */
1630*1a4e3449SJack F Vogel 	if (index >= rar_entries) {
1631*1a4e3449SJack F Vogel 		DEBUGOUT1("RAR index %d is out of range.\n", index);
1632*1a4e3449SJack F Vogel 		return IXGBE_ERR_INVALID_ARGUMENT;
1633*1a4e3449SJack F Vogel 	}
1634*1a4e3449SJack F Vogel 
16355b7f4cedSJack F Vogel 	/*
16365b7f4cedSJack F Vogel 	 * Some parts put the VMDq setting in the extra RAH bits,
16375b7f4cedSJack F Vogel 	 * so save everything except the lower 16 bits that hold part
16385b7f4cedSJack F Vogel 	 * of the address and the address valid bit.
16395b7f4cedSJack F Vogel 	 */
16405b7f4cedSJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
16415b7f4cedSJack F Vogel 	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
16425b7f4cedSJack F Vogel 
16435b7f4cedSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
16445b7f4cedSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
16455b7f4cedSJack F Vogel 
16465b7f4cedSJack F Vogel 	/* clear VMDq pool/queue selection for this RAR */
16475b7f4cedSJack F Vogel 	hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
16485b7f4cedSJack F Vogel 
16495b7f4cedSJack F Vogel 	return IXGBE_SUCCESS;
16505b7f4cedSJack F Vogel }
16515b7f4cedSJack F Vogel 
16525b7f4cedSJack F Vogel /**
165313705f88SJack F Vogel  *  ixgbe_init_rx_addrs_generic - Initializes receive address filters.
165413705f88SJack F Vogel  *  @hw: pointer to hardware structure
165513705f88SJack F Vogel  *
165613705f88SJack F Vogel  *  Places the MAC address in receive address register 0 and clears the rest
16579ca4041bSJack F Vogel  *  of the receive address registers. Clears the multicast table. Assumes
165813705f88SJack F Vogel  *  the receiver is in reset when the routine is called.
165913705f88SJack F Vogel  **/
166013705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
166113705f88SJack F Vogel {
166213705f88SJack F Vogel 	u32 i;
16639ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
166413705f88SJack F Vogel 
16652969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_rx_addrs_generic");
16662969bf0eSJack F Vogel 
166713705f88SJack F Vogel 	/*
166813705f88SJack F Vogel 	 * If the current mac address is valid, assume it is a software override
166913705f88SJack F Vogel 	 * to the permanent address.
167013705f88SJack F Vogel 	 * Otherwise, use the permanent address from the eeprom.
167113705f88SJack F Vogel 	 */
167213705f88SJack F Vogel 	if (ixgbe_validate_mac_addr(hw->mac.addr) ==
167313705f88SJack F Vogel 	    IXGBE_ERR_INVALID_MAC_ADDR) {
167413705f88SJack F Vogel 		/* Get the MAC address from the RAR0 for later reference */
16759ca4041bSJack F Vogel 		hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
167613705f88SJack F Vogel 
167713705f88SJack F Vogel 		DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
167813705f88SJack F Vogel 		          hw->mac.addr[0], hw->mac.addr[1],
167913705f88SJack F Vogel 		          hw->mac.addr[2]);
168013705f88SJack F Vogel 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
168113705f88SJack F Vogel 		          hw->mac.addr[4], hw->mac.addr[5]);
168213705f88SJack F Vogel 	} else {
168313705f88SJack F Vogel 		/* Setup the receive address. */
168413705f88SJack F Vogel 		DEBUGOUT("Overriding MAC Address in RAR[0]\n");
168513705f88SJack F Vogel 		DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
168613705f88SJack F Vogel 		          hw->mac.addr[0], hw->mac.addr[1],
168713705f88SJack F Vogel 		          hw->mac.addr[2]);
168813705f88SJack F Vogel 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
168913705f88SJack F Vogel 		          hw->mac.addr[4], hw->mac.addr[5]);
169013705f88SJack F Vogel 
16919ca4041bSJack F Vogel 		hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
169213705f88SJack F Vogel 	}
16939ca4041bSJack F Vogel 	hw->addr_ctrl.overflow_promisc = 0;
169413705f88SJack F Vogel 
169513705f88SJack F Vogel 	hw->addr_ctrl.rar_used_count = 1;
169613705f88SJack F Vogel 
169713705f88SJack F Vogel 	/* Zero out the other receive addresses. */
16989ca4041bSJack F Vogel 	DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1);
169913705f88SJack F Vogel 	for (i = 1; i < rar_entries; i++) {
170013705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
170113705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
170213705f88SJack F Vogel 	}
170313705f88SJack F Vogel 
170413705f88SJack F Vogel 	/* Clear the MTA */
170513705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use = 0;
170613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
170713705f88SJack F Vogel 
170813705f88SJack F Vogel 	DEBUGOUT(" Clearing MTA\n");
17099ca4041bSJack F Vogel 	for (i = 0; i < hw->mac.mcft_size; i++)
171013705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
171113705f88SJack F Vogel 
17125b7f4cedSJack F Vogel 	ixgbe_init_uta_tables(hw);
17135b7f4cedSJack F Vogel 
171413705f88SJack F Vogel 	return IXGBE_SUCCESS;
171513705f88SJack F Vogel }
171613705f88SJack F Vogel 
171713705f88SJack F Vogel /**
17189ca4041bSJack F Vogel  *  ixgbe_add_uc_addr - Adds a secondary unicast address.
17199ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
17209ca4041bSJack F Vogel  *  @addr: new address
17219ca4041bSJack F Vogel  *
17229ca4041bSJack F Vogel  *  Adds it to unused receive address register or goes into promiscuous mode.
17239ca4041bSJack F Vogel  **/
17249ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
17259ca4041bSJack F Vogel {
17269ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
17279ca4041bSJack F Vogel 	u32 rar;
17289ca4041bSJack F Vogel 
17292969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_add_uc_addr");
17302969bf0eSJack F Vogel 
17319ca4041bSJack F Vogel 	DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
17329ca4041bSJack F Vogel 	          addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
17339ca4041bSJack F Vogel 
17349ca4041bSJack F Vogel 	/*
17359ca4041bSJack F Vogel 	 * Place this address in the RAR if there is room,
17369ca4041bSJack F Vogel 	 * else put the controller into promiscuous mode
17379ca4041bSJack F Vogel 	 */
17389ca4041bSJack F Vogel 	if (hw->addr_ctrl.rar_used_count < rar_entries) {
17390ac6dfecSJack F Vogel 		rar = hw->addr_ctrl.rar_used_count;
17409ca4041bSJack F Vogel 		hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
17419ca4041bSJack F Vogel 		DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar);
17429ca4041bSJack F Vogel 		hw->addr_ctrl.rar_used_count++;
17439ca4041bSJack F Vogel 	} else {
17449ca4041bSJack F Vogel 		hw->addr_ctrl.overflow_promisc++;
17459ca4041bSJack F Vogel 	}
17469ca4041bSJack F Vogel 
17479ca4041bSJack F Vogel 	DEBUGOUT("ixgbe_add_uc_addr Complete\n");
17489ca4041bSJack F Vogel }
17499ca4041bSJack F Vogel 
17509ca4041bSJack F Vogel /**
17519ca4041bSJack F Vogel  *  ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
17529ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
17539ca4041bSJack F Vogel  *  @addr_list: the list of new addresses
17549ca4041bSJack F Vogel  *  @addr_count: number of addresses
17559ca4041bSJack F Vogel  *  @next: iterator function to walk the address list
17569ca4041bSJack F Vogel  *
17579ca4041bSJack F Vogel  *  The given list replaces any existing list.  Clears the secondary addrs from
17589ca4041bSJack F Vogel  *  receive address registers.  Uses unused receive address registers for the
17599ca4041bSJack F Vogel  *  first secondary addresses, and falls back to promiscuous mode as needed.
17609ca4041bSJack F Vogel  *
17619ca4041bSJack F Vogel  *  Drivers using secondary unicast addresses must set user_set_promisc when
17629ca4041bSJack F Vogel  *  manually putting the device into promiscuous mode.
17639ca4041bSJack F Vogel  **/
17649ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
17659ca4041bSJack F Vogel                                       u32 addr_count, ixgbe_mc_addr_itr next)
17669ca4041bSJack F Vogel {
17679ca4041bSJack F Vogel 	u8 *addr;
17689ca4041bSJack F Vogel 	u32 i;
17699ca4041bSJack F Vogel 	u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
17709ca4041bSJack F Vogel 	u32 uc_addr_in_use;
17719ca4041bSJack F Vogel 	u32 fctrl;
17729ca4041bSJack F Vogel 	u32 vmdq;
17739ca4041bSJack F Vogel 
17742969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_update_uc_addr_list_generic");
17752969bf0eSJack F Vogel 
17769ca4041bSJack F Vogel 	/*
17779ca4041bSJack F Vogel 	 * Clear accounting of old secondary address list,
17789ca4041bSJack F Vogel 	 * don't count RAR[0]
17799ca4041bSJack F Vogel 	 */
17800ac6dfecSJack F Vogel 	uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1;
17819ca4041bSJack F Vogel 	hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
17829ca4041bSJack F Vogel 	hw->addr_ctrl.overflow_promisc = 0;
17839ca4041bSJack F Vogel 
17849ca4041bSJack F Vogel 	/* Zero out the other receive addresses */
17852969bf0eSJack F Vogel 	DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1);
17862969bf0eSJack F Vogel 	for (i = 0; i < uc_addr_in_use; i++) {
17872969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0);
17882969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0);
17899ca4041bSJack F Vogel 	}
17909ca4041bSJack F Vogel 
17919ca4041bSJack F Vogel 	/* Add the new addresses */
17929ca4041bSJack F Vogel 	for (i = 0; i < addr_count; i++) {
17939ca4041bSJack F Vogel 		DEBUGOUT(" Adding the secondary addresses:\n");
17949ca4041bSJack F Vogel 		addr = next(hw, &addr_list, &vmdq);
17959ca4041bSJack F Vogel 		ixgbe_add_uc_addr(hw, addr, vmdq);
17969ca4041bSJack F Vogel 	}
17979ca4041bSJack F Vogel 
17989ca4041bSJack F Vogel 	if (hw->addr_ctrl.overflow_promisc) {
17999ca4041bSJack F Vogel 		/* enable promisc if not already in overflow or set by user */
18009ca4041bSJack F Vogel 		if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
18019ca4041bSJack F Vogel 			DEBUGOUT(" Entering address overflow promisc mode\n");
18029ca4041bSJack F Vogel 			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
18039ca4041bSJack F Vogel 			fctrl |= IXGBE_FCTRL_UPE;
18049ca4041bSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
18059ca4041bSJack F Vogel 		}
18069ca4041bSJack F Vogel 	} else {
18079ca4041bSJack F Vogel 		/* only disable if set by overflow, not by user */
18089ca4041bSJack F Vogel 		if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
18099ca4041bSJack F Vogel 			DEBUGOUT(" Leaving address overflow promisc mode\n");
18109ca4041bSJack F Vogel 			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
18119ca4041bSJack F Vogel 			fctrl &= ~IXGBE_FCTRL_UPE;
18129ca4041bSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
18139ca4041bSJack F Vogel 		}
18149ca4041bSJack F Vogel 	}
18159ca4041bSJack F Vogel 
18169ca4041bSJack F Vogel 	DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n");
18179ca4041bSJack F Vogel 	return IXGBE_SUCCESS;
18189ca4041bSJack F Vogel }
18199ca4041bSJack F Vogel 
18209ca4041bSJack F Vogel /**
182113705f88SJack F Vogel  *  ixgbe_mta_vector - Determines bit-vector in multicast table to set
182213705f88SJack F Vogel  *  @hw: pointer to hardware structure
182313705f88SJack F Vogel  *  @mc_addr: the multicast address
182413705f88SJack F Vogel  *
182513705f88SJack F Vogel  *  Extracts the 12 bits, from a multicast address, to determine which
182613705f88SJack F Vogel  *  bit-vector to set in the multicast table. The hardware uses 12 bits, from
182713705f88SJack F Vogel  *  incoming rx multicast addresses, to determine the bit-vector to check in
182813705f88SJack F Vogel  *  the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
18299ca4041bSJack F Vogel  *  by the MO field of the MCSTCTRL. The MO field is set during initialization
183013705f88SJack F Vogel  *  to mc_filter_type.
183113705f88SJack F Vogel  **/
183213705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
183313705f88SJack F Vogel {
183413705f88SJack F Vogel 	u32 vector = 0;
183513705f88SJack F Vogel 
18362969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_mta_vector");
18372969bf0eSJack F Vogel 
183813705f88SJack F Vogel 	switch (hw->mac.mc_filter_type) {
183913705f88SJack F Vogel 	case 0:   /* use bits [47:36] of the address */
184013705f88SJack F Vogel 		vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
184113705f88SJack F Vogel 		break;
184213705f88SJack F Vogel 	case 1:   /* use bits [46:35] of the address */
184313705f88SJack F Vogel 		vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
184413705f88SJack F Vogel 		break;
184513705f88SJack F Vogel 	case 2:   /* use bits [45:34] of the address */
184613705f88SJack F Vogel 		vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
184713705f88SJack F Vogel 		break;
184813705f88SJack F Vogel 	case 3:   /* use bits [43:32] of the address */
184913705f88SJack F Vogel 		vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
185013705f88SJack F Vogel 		break;
185113705f88SJack F Vogel 	default:  /* Invalid mc_filter_type */
185213705f88SJack F Vogel 		DEBUGOUT("MC filter type param set incorrectly\n");
185313705f88SJack F Vogel 		ASSERT(0);
185413705f88SJack F Vogel 		break;
185513705f88SJack F Vogel 	}
185613705f88SJack F Vogel 
185713705f88SJack F Vogel 	/* vector can only be 12-bits or boundary will be exceeded */
185813705f88SJack F Vogel 	vector &= 0xFFF;
185913705f88SJack F Vogel 	return vector;
186013705f88SJack F Vogel }
186113705f88SJack F Vogel 
186213705f88SJack F Vogel /**
186313705f88SJack F Vogel  *  ixgbe_set_mta - Set bit-vector in multicast table
186413705f88SJack F Vogel  *  @hw: pointer to hardware structure
186513705f88SJack F Vogel  *  @hash_value: Multicast address hash value
186613705f88SJack F Vogel  *
186713705f88SJack F Vogel  *  Sets the bit-vector in the multicast table.
186813705f88SJack F Vogel  **/
186913705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
187013705f88SJack F Vogel {
187113705f88SJack F Vogel 	u32 vector;
187213705f88SJack F Vogel 	u32 vector_bit;
187313705f88SJack F Vogel 	u32 vector_reg;
187413705f88SJack F Vogel 
18752969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_mta");
18762969bf0eSJack F Vogel 
187713705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use++;
187813705f88SJack F Vogel 
187913705f88SJack F Vogel 	vector = ixgbe_mta_vector(hw, mc_addr);
188013705f88SJack F Vogel 	DEBUGOUT1(" bit-vector = 0x%03X\n", vector);
188113705f88SJack F Vogel 
188213705f88SJack F Vogel 	/*
188313705f88SJack F Vogel 	 * The MTA is a register array of 128 32-bit registers. It is treated
188413705f88SJack F Vogel 	 * like an array of 4096 bits.  We want to set bit
188513705f88SJack F Vogel 	 * BitArray[vector_value]. So we figure out what register the bit is
188613705f88SJack F Vogel 	 * in, read it, OR in the new bit, then write back the new value.  The
188713705f88SJack F Vogel 	 * register is determined by the upper 7 bits of the vector value and
188813705f88SJack F Vogel 	 * the bit within that register are determined by the lower 5 bits of
188913705f88SJack F Vogel 	 * the value.
189013705f88SJack F Vogel 	 */
189113705f88SJack F Vogel 	vector_reg = (vector >> 5) & 0x7F;
189213705f88SJack F Vogel 	vector_bit = vector & 0x1F;
1893*1a4e3449SJack F Vogel 	hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit);
189413705f88SJack F Vogel }
189513705f88SJack F Vogel 
189613705f88SJack F Vogel /**
189713705f88SJack F Vogel  *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
189813705f88SJack F Vogel  *  @hw: pointer to hardware structure
189913705f88SJack F Vogel  *  @mc_addr_list: the list of new multicast addresses
190013705f88SJack F Vogel  *  @mc_addr_count: number of addresses
19019ca4041bSJack F Vogel  *  @next: iterator function to walk the multicast address list
190213705f88SJack F Vogel  *
190313705f88SJack F Vogel  *  The given list replaces any existing list. Clears the MC addrs from receive
19049ca4041bSJack F Vogel  *  address registers and the multicast table. Uses unused receive address
190513705f88SJack F Vogel  *  registers for the first multicast addresses, and hashes the rest into the
190613705f88SJack F Vogel  *  multicast table.
190713705f88SJack F Vogel  **/
190813705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
19099ca4041bSJack F Vogel                                       u32 mc_addr_count, ixgbe_mc_addr_itr next)
191013705f88SJack F Vogel {
191113705f88SJack F Vogel 	u32 i;
19129ca4041bSJack F Vogel 	u32 vmdq;
191313705f88SJack F Vogel 
19142969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_update_mc_addr_list_generic");
19152969bf0eSJack F Vogel 
191613705f88SJack F Vogel 	/*
191713705f88SJack F Vogel 	 * Set the new number of MC addresses that we are being requested to
191813705f88SJack F Vogel 	 * use.
191913705f88SJack F Vogel 	 */
192013705f88SJack F Vogel 	hw->addr_ctrl.num_mc_addrs = mc_addr_count;
192113705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use = 0;
192213705f88SJack F Vogel 
1923*1a4e3449SJack F Vogel 	/* Clear mta_shadow */
192413705f88SJack F Vogel 	DEBUGOUT(" Clearing MTA\n");
1925*1a4e3449SJack F Vogel 	memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
192613705f88SJack F Vogel 
1927*1a4e3449SJack F Vogel 	/* Update mta_shadow */
192813705f88SJack F Vogel 	for (i = 0; i < mc_addr_count; i++) {
192913705f88SJack F Vogel 		DEBUGOUT(" Adding the multicast addresses:\n");
19300ac6dfecSJack F Vogel 		ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq));
193113705f88SJack F Vogel 	}
193213705f88SJack F Vogel 
193313705f88SJack F Vogel 	/* Enable mta */
1934*1a4e3449SJack F Vogel 	for (i = 0; i < hw->mac.mcft_size; i++)
1935*1a4e3449SJack F Vogel 		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i,
1936*1a4e3449SJack F Vogel 				      hw->mac.mta_shadow[i]);
1937*1a4e3449SJack F Vogel 
193813705f88SJack F Vogel 	if (hw->addr_ctrl.mta_in_use > 0)
193913705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
194013705f88SJack F Vogel 		                IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
194113705f88SJack F Vogel 
194213705f88SJack F Vogel 	DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n");
194313705f88SJack F Vogel 	return IXGBE_SUCCESS;
194413705f88SJack F Vogel }
194513705f88SJack F Vogel 
194613705f88SJack F Vogel /**
194713705f88SJack F Vogel  *  ixgbe_enable_mc_generic - Enable multicast address in RAR
194813705f88SJack F Vogel  *  @hw: pointer to hardware structure
194913705f88SJack F Vogel  *
195013705f88SJack F Vogel  *  Enables multicast address in RAR and the use of the multicast hash table.
195113705f88SJack F Vogel  **/
195213705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
195313705f88SJack F Vogel {
195413705f88SJack F Vogel 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
195513705f88SJack F Vogel 
19562969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_enable_mc_generic");
19572969bf0eSJack F Vogel 
195813705f88SJack F Vogel 	if (a->mta_in_use > 0)
195913705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
196013705f88SJack F Vogel 		                hw->mac.mc_filter_type);
196113705f88SJack F Vogel 
196213705f88SJack F Vogel 	return IXGBE_SUCCESS;
196313705f88SJack F Vogel }
196413705f88SJack F Vogel 
196513705f88SJack F Vogel /**
19669ca4041bSJack F Vogel  *  ixgbe_disable_mc_generic - Disable multicast address in RAR
196713705f88SJack F Vogel  *  @hw: pointer to hardware structure
196813705f88SJack F Vogel  *
196913705f88SJack F Vogel  *  Disables multicast address in RAR and the use of the multicast hash table.
197013705f88SJack F Vogel  **/
197113705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
197213705f88SJack F Vogel {
197313705f88SJack F Vogel 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
197413705f88SJack F Vogel 
19752969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_disable_mc_generic");
19762969bf0eSJack F Vogel 
197713705f88SJack F Vogel 	if (a->mta_in_use > 0)
197813705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
197913705f88SJack F Vogel 
198013705f88SJack F Vogel 	return IXGBE_SUCCESS;
198113705f88SJack F Vogel }
198213705f88SJack F Vogel 
19831b6e0dbaSJack F Vogel /**
19840ac6dfecSJack F Vogel  *  ixgbe_fc_enable_generic - Enable flow control
19851b6e0dbaSJack F Vogel  *  @hw: pointer to hardware structure
19860ac6dfecSJack F Vogel  *  @packetbuf_num: packet buffer number (0-7)
19871b6e0dbaSJack F Vogel  *
19880ac6dfecSJack F Vogel  *  Enable flow control according to the current settings.
19891b6e0dbaSJack F Vogel  **/
19900ac6dfecSJack F Vogel s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
19911b6e0dbaSJack F Vogel {
19921b6e0dbaSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
19930ac6dfecSJack F Vogel 	u32 mflcn_reg, fccfg_reg;
19940ac6dfecSJack F Vogel 	u32 reg;
1995d8602bb9SJack F Vogel 	u32 rx_pba_size;
1996*1a4e3449SJack F Vogel 	u32 fcrtl, fcrth;
19971b6e0dbaSJack F Vogel 
19980ac6dfecSJack F Vogel 	DEBUGFUNC("ixgbe_fc_enable_generic");
19991b6e0dbaSJack F Vogel 
20000ac6dfecSJack F Vogel 	/* Negotiate the fc mode to use */
20010ac6dfecSJack F Vogel 	ret_val = ixgbe_fc_autoneg(hw);
2002*1a4e3449SJack F Vogel 	if (ret_val == IXGBE_ERR_FLOW_CONTROL)
20030ac6dfecSJack F Vogel 		goto out;
20040ac6dfecSJack F Vogel 
20050ac6dfecSJack F Vogel 	/* Disable any previous flow control settings */
20060ac6dfecSJack F Vogel 	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
20070ac6dfecSJack F Vogel 	mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
20080ac6dfecSJack F Vogel 
20090ac6dfecSJack F Vogel 	fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
20100ac6dfecSJack F Vogel 	fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
20111b6e0dbaSJack F Vogel 
20121b6e0dbaSJack F Vogel 	/*
20131b6e0dbaSJack F Vogel 	 * The possible values of fc.current_mode are:
20141b6e0dbaSJack F Vogel 	 * 0: Flow control is completely disabled
20151b6e0dbaSJack F Vogel 	 * 1: Rx flow control is enabled (we can receive pause frames,
20161b6e0dbaSJack F Vogel 	 *    but not send pause frames).
20171b6e0dbaSJack F Vogel 	 * 2: Tx flow control is enabled (we can send pause frames but
20181b6e0dbaSJack F Vogel 	 *    we do not support receiving pause frames).
20191b6e0dbaSJack F Vogel 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
20201b6e0dbaSJack F Vogel 	 * other: Invalid.
20211b6e0dbaSJack F Vogel 	 */
20221b6e0dbaSJack F Vogel 	switch (hw->fc.current_mode) {
20231b6e0dbaSJack F Vogel 	case ixgbe_fc_none:
2024*1a4e3449SJack F Vogel 		/*
2025*1a4e3449SJack F Vogel 		 * Flow control is disabled by software override or autoneg.
20260ac6dfecSJack F Vogel 		 * The code below will actually disable it in the HW.
20270ac6dfecSJack F Vogel 		 */
20281b6e0dbaSJack F Vogel 		break;
20291b6e0dbaSJack F Vogel 	case ixgbe_fc_rx_pause:
20301b6e0dbaSJack F Vogel 		/*
20311b6e0dbaSJack F Vogel 		 * Rx Flow control is enabled and Tx Flow control is
20321b6e0dbaSJack F Vogel 		 * disabled by software override. Since there really
20331b6e0dbaSJack F Vogel 		 * isn't a way to advertise that we are capable of RX
20341b6e0dbaSJack F Vogel 		 * Pause ONLY, we will advertise that we support both
20351b6e0dbaSJack F Vogel 		 * symmetric and asymmetric Rx PAUSE.  Later, we will
20361b6e0dbaSJack F Vogel 		 * disable the adapter's ability to send PAUSE frames.
20371b6e0dbaSJack F Vogel 		 */
20380ac6dfecSJack F Vogel 		mflcn_reg |= IXGBE_MFLCN_RFCE;
20391b6e0dbaSJack F Vogel 		break;
20401b6e0dbaSJack F Vogel 	case ixgbe_fc_tx_pause:
20411b6e0dbaSJack F Vogel 		/*
20421b6e0dbaSJack F Vogel 		 * Tx Flow control is enabled, and Rx Flow control is
20431b6e0dbaSJack F Vogel 		 * disabled by software override.
20441b6e0dbaSJack F Vogel 		 */
20450ac6dfecSJack F Vogel 		fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
20461b6e0dbaSJack F Vogel 		break;
20471b6e0dbaSJack F Vogel 	case ixgbe_fc_full:
20481b6e0dbaSJack F Vogel 		/* Flow control (both Rx and Tx) is enabled by SW override. */
20490ac6dfecSJack F Vogel 		mflcn_reg |= IXGBE_MFLCN_RFCE;
20500ac6dfecSJack F Vogel 		fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
20511b6e0dbaSJack F Vogel 		break;
20521b6e0dbaSJack F Vogel 	default:
20531b6e0dbaSJack F Vogel 		DEBUGOUT("Flow control param set incorrectly\n");
20542969bf0eSJack F Vogel 		ret_val = IXGBE_ERR_CONFIG;
20551b6e0dbaSJack F Vogel 		goto out;
20561b6e0dbaSJack F Vogel 		break;
20571b6e0dbaSJack F Vogel 	}
20581b6e0dbaSJack F Vogel 
20590ac6dfecSJack F Vogel 	/* Set 802.3x based flow control settings. */
20600ac6dfecSJack F Vogel 	mflcn_reg |= IXGBE_MFLCN_DPF;
20610ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
20620ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
20631b6e0dbaSJack F Vogel 
2064d8602bb9SJack F Vogel 	rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
2065*1a4e3449SJack F Vogel 	rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
2066d8602bb9SJack F Vogel 
2067*1a4e3449SJack F Vogel 	fcrth = (rx_pba_size - hw->fc.high_water) << 10;
2068*1a4e3449SJack F Vogel 	fcrtl = (rx_pba_size - hw->fc.low_water) << 10;
2069d8602bb9SJack F Vogel 
20700ac6dfecSJack F Vogel 	if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
2071*1a4e3449SJack F Vogel 		fcrth |= IXGBE_FCRTH_FCEN;
2072*1a4e3449SJack F Vogel 		if (hw->fc.send_xon)
2073*1a4e3449SJack F Vogel 			fcrtl |= IXGBE_FCRTL_XONE;
20741b6e0dbaSJack F Vogel 	}
20751b6e0dbaSJack F Vogel 
2076*1a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth);
2077*1a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), fcrtl);
20780ac6dfecSJack F Vogel 
20790ac6dfecSJack F Vogel 	/* Configure pause time (2 TCs per register) */
2080d8602bb9SJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
20810ac6dfecSJack F Vogel 	if ((packetbuf_num & 1) == 0)
20820ac6dfecSJack F Vogel 		reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
20830ac6dfecSJack F Vogel 	else
20840ac6dfecSJack F Vogel 		reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
20850ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
20860ac6dfecSJack F Vogel 
20870ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
20880ac6dfecSJack F Vogel 
20890ac6dfecSJack F Vogel out:
20900ac6dfecSJack F Vogel 	return ret_val;
20910ac6dfecSJack F Vogel }
20920ac6dfecSJack F Vogel 
20930ac6dfecSJack F Vogel /**
20940ac6dfecSJack F Vogel  *  ixgbe_fc_autoneg - Configure flow control
20950ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
20960ac6dfecSJack F Vogel  *
20970ac6dfecSJack F Vogel  *  Compares our advertised flow control capabilities to those advertised by
20980ac6dfecSJack F Vogel  *  our link partner, and determines the proper flow control mode to use.
20990ac6dfecSJack F Vogel  **/
21000ac6dfecSJack F Vogel s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
21010ac6dfecSJack F Vogel {
2102*1a4e3449SJack F Vogel 	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
21030ac6dfecSJack F Vogel 	ixgbe_link_speed speed;
21040ac6dfecSJack F Vogel 	bool link_up;
21050ac6dfecSJack F Vogel 
21060ac6dfecSJack F Vogel 	DEBUGFUNC("ixgbe_fc_autoneg");
21070ac6dfecSJack F Vogel 
2108*1a4e3449SJack F Vogel 	if (hw->fc.disable_fc_autoneg)
2109*1a4e3449SJack F Vogel 		goto out;
2110*1a4e3449SJack F Vogel 
21110ac6dfecSJack F Vogel 	/*
21120ac6dfecSJack F Vogel 	 * AN should have completed when the cable was plugged in.
21130ac6dfecSJack F Vogel 	 * Look for reasons to bail out.  Bail out if:
21140ac6dfecSJack F Vogel 	 * - FC autoneg is disabled, or if
21152969bf0eSJack F Vogel 	 * - link is not up.
21160ac6dfecSJack F Vogel 	 *
21172969bf0eSJack F Vogel 	 * Since we're being called from an LSC, link is already known to be up.
21180ac6dfecSJack F Vogel 	 * So use link_up_wait_to_complete=FALSE.
21190ac6dfecSJack F Vogel 	 */
21200ac6dfecSJack F Vogel 	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
2121*1a4e3449SJack F Vogel 	if (!link_up) {
2122*1a4e3449SJack F Vogel 		ret_val = IXGBE_ERR_FLOW_CONTROL;
21232969bf0eSJack F Vogel 		goto out;
21242969bf0eSJack F Vogel 	}
21252969bf0eSJack F Vogel 
2126*1a4e3449SJack F Vogel 	switch (hw->phy.media_type) {
2127*1a4e3449SJack F Vogel 	/* Autoneg flow control on fiber adapters */
2128*1a4e3449SJack F Vogel 	case ixgbe_media_type_fiber:
2129*1a4e3449SJack F Vogel 		if (speed == IXGBE_LINK_SPEED_1GB_FULL)
2130*1a4e3449SJack F Vogel 			ret_val = ixgbe_fc_autoneg_fiber(hw);
2131*1a4e3449SJack F Vogel 		break;
2132*1a4e3449SJack F Vogel 
2133*1a4e3449SJack F Vogel 	/* Autoneg flow control on backplane adapters */
2134*1a4e3449SJack F Vogel 	case ixgbe_media_type_backplane:
2135*1a4e3449SJack F Vogel 		ret_val = ixgbe_fc_autoneg_backplane(hw);
2136*1a4e3449SJack F Vogel 		break;
2137*1a4e3449SJack F Vogel 
2138*1a4e3449SJack F Vogel 	/* Autoneg flow control on copper adapters */
2139*1a4e3449SJack F Vogel 	case ixgbe_media_type_copper:
2140*1a4e3449SJack F Vogel 		if (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)
2141*1a4e3449SJack F Vogel 			ret_val = ixgbe_fc_autoneg_copper(hw);
2142*1a4e3449SJack F Vogel 		break;
2143*1a4e3449SJack F Vogel 
2144*1a4e3449SJack F Vogel 	default:
2145*1a4e3449SJack F Vogel 		break;
2146*1a4e3449SJack F Vogel 	}
2147*1a4e3449SJack F Vogel 
2148*1a4e3449SJack F Vogel out:
2149*1a4e3449SJack F Vogel 	if (ret_val == IXGBE_SUCCESS) {
2150*1a4e3449SJack F Vogel 		hw->fc.fc_was_autonegged = TRUE;
2151*1a4e3449SJack F Vogel 	} else {
2152*1a4e3449SJack F Vogel 		hw->fc.fc_was_autonegged = FALSE;
2153*1a4e3449SJack F Vogel 		hw->fc.current_mode = hw->fc.requested_mode;
2154*1a4e3449SJack F Vogel 	}
2155*1a4e3449SJack F Vogel 	return ret_val;
2156*1a4e3449SJack F Vogel }
2157*1a4e3449SJack F Vogel 
2158*1a4e3449SJack F Vogel /**
2159*1a4e3449SJack F Vogel  *  ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
2160*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
2161*1a4e3449SJack F Vogel  *  @speed:
2162*1a4e3449SJack F Vogel  *  @link_up
2163*1a4e3449SJack F Vogel  *
2164*1a4e3449SJack F Vogel  *  Enable flow control according on 1 gig fiber.
2165*1a4e3449SJack F Vogel  **/
2166*1a4e3449SJack F Vogel static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
2167*1a4e3449SJack F Vogel {
2168*1a4e3449SJack F Vogel 	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
2169*1a4e3449SJack F Vogel 	s32 ret_val;
2170*1a4e3449SJack F Vogel 
2171*1a4e3449SJack F Vogel 	/*
2172*1a4e3449SJack F Vogel 	 * On multispeed fiber at 1g, bail out if
2173*1a4e3449SJack F Vogel 	 * - link is up but AN did not complete, or if
2174*1a4e3449SJack F Vogel 	 * - link is up and AN completed but timed out
2175*1a4e3449SJack F Vogel 	 */
2176*1a4e3449SJack F Vogel 
2177*1a4e3449SJack F Vogel 	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
2178*1a4e3449SJack F Vogel 	if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
2179*1a4e3449SJack F Vogel 	    ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
2180*1a4e3449SJack F Vogel 		ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
2181*1a4e3449SJack F Vogel 		goto out;
2182*1a4e3449SJack F Vogel 	}
2183*1a4e3449SJack F Vogel 
2184*1a4e3449SJack F Vogel 	pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
2185*1a4e3449SJack F Vogel 	pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
2186*1a4e3449SJack F Vogel 
2187*1a4e3449SJack F Vogel 	ret_val =  ixgbe_negotiate_fc(hw, pcs_anadv_reg,
2188*1a4e3449SJack F Vogel 			       pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE,
2189*1a4e3449SJack F Vogel 			       IXGBE_PCS1GANA_ASM_PAUSE,
2190*1a4e3449SJack F Vogel 			       IXGBE_PCS1GANA_SYM_PAUSE,
2191*1a4e3449SJack F Vogel 			       IXGBE_PCS1GANA_ASM_PAUSE);
2192*1a4e3449SJack F Vogel 
2193*1a4e3449SJack F Vogel out:
2194*1a4e3449SJack F Vogel 	return ret_val;
2195*1a4e3449SJack F Vogel }
2196*1a4e3449SJack F Vogel 
2197*1a4e3449SJack F Vogel /**
2198*1a4e3449SJack F Vogel  *  ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37
2199*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
2200*1a4e3449SJack F Vogel  *
2201*1a4e3449SJack F Vogel  *  Enable flow control according to IEEE clause 37.
2202*1a4e3449SJack F Vogel  **/
2203*1a4e3449SJack F Vogel static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
2204*1a4e3449SJack F Vogel {
2205*1a4e3449SJack F Vogel 	u32 links2, anlp1_reg, autoc_reg, links;
2206*1a4e3449SJack F Vogel 	s32 ret_val;
2207*1a4e3449SJack F Vogel 
22082969bf0eSJack F Vogel 	/*
22092969bf0eSJack F Vogel 	 * On backplane, bail out if
22102969bf0eSJack F Vogel 	 * - backplane autoneg was not completed, or if
22112969bf0eSJack F Vogel 	 * - we are 82599 and link partner is not AN enabled
22122969bf0eSJack F Vogel 	 */
22132969bf0eSJack F Vogel 	links = IXGBE_READ_REG(hw, IXGBE_LINKS);
22142969bf0eSJack F Vogel 	if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
22152969bf0eSJack F Vogel 		hw->fc.fc_was_autonegged = FALSE;
22162969bf0eSJack F Vogel 		hw->fc.current_mode = hw->fc.requested_mode;
2217*1a4e3449SJack F Vogel 		ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
22182969bf0eSJack F Vogel 		goto out;
22192969bf0eSJack F Vogel 	}
22202969bf0eSJack F Vogel 
22212969bf0eSJack F Vogel 	if (hw->mac.type == ixgbe_mac_82599EB) {
22222969bf0eSJack F Vogel 		links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
22232969bf0eSJack F Vogel 		if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
22242969bf0eSJack F Vogel 			hw->fc.fc_was_autonegged = FALSE;
22252969bf0eSJack F Vogel 			hw->fc.current_mode = hw->fc.requested_mode;
2226*1a4e3449SJack F Vogel 			ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
22272969bf0eSJack F Vogel 			goto out;
22282969bf0eSJack F Vogel 		}
22292969bf0eSJack F Vogel 	}
22302969bf0eSJack F Vogel 	/*
22312969bf0eSJack F Vogel 	 * Read the 10g AN autoc and LP ability registers and resolve
22322969bf0eSJack F Vogel 	 * local flow control settings accordingly
22332969bf0eSJack F Vogel 	 */
22342969bf0eSJack F Vogel 	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
22352969bf0eSJack F Vogel 	anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
22362969bf0eSJack F Vogel 
2237*1a4e3449SJack F Vogel 	ret_val = ixgbe_negotiate_fc(hw, autoc_reg,
2238*1a4e3449SJack F Vogel 		anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE,
2239*1a4e3449SJack F Vogel 		IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE);
2240*1a4e3449SJack F Vogel 
2241*1a4e3449SJack F Vogel out:
2242*1a4e3449SJack F Vogel 	return ret_val;
2243*1a4e3449SJack F Vogel }
2244*1a4e3449SJack F Vogel 
2245*1a4e3449SJack F Vogel /**
2246*1a4e3449SJack F Vogel  *  ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37
2247*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
2248*1a4e3449SJack F Vogel  *
2249*1a4e3449SJack F Vogel  *  Enable flow control according to IEEE clause 37.
2250*1a4e3449SJack F Vogel  **/
2251*1a4e3449SJack F Vogel static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw)
2252*1a4e3449SJack F Vogel {
2253*1a4e3449SJack F Vogel 	u16 technology_ability_reg = 0;
2254*1a4e3449SJack F Vogel 	u16 lp_technology_ability_reg = 0;
2255*1a4e3449SJack F Vogel 
2256*1a4e3449SJack F Vogel 	hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
2257*1a4e3449SJack F Vogel 			     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
2258*1a4e3449SJack F Vogel 			     &technology_ability_reg);
2259*1a4e3449SJack F Vogel 	hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP,
2260*1a4e3449SJack F Vogel 			     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
2261*1a4e3449SJack F Vogel 			     &lp_technology_ability_reg);
2262*1a4e3449SJack F Vogel 
2263*1a4e3449SJack F Vogel 	return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg,
2264*1a4e3449SJack F Vogel 				  (u32)lp_technology_ability_reg,
2265*1a4e3449SJack F Vogel 				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE,
2266*1a4e3449SJack F Vogel 				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE);
2267*1a4e3449SJack F Vogel }
2268*1a4e3449SJack F Vogel 
2269*1a4e3449SJack F Vogel /**
2270*1a4e3449SJack F Vogel  *  ixgbe_negotiate_fc - Negotiate flow control
2271*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
2272*1a4e3449SJack F Vogel  *  @adv_reg: flow control advertised settings
2273*1a4e3449SJack F Vogel  *  @lp_reg: link partner's flow control settings
2274*1a4e3449SJack F Vogel  *  @adv_sym: symmetric pause bit in advertisement
2275*1a4e3449SJack F Vogel  *  @adv_asm: asymmetric pause bit in advertisement
2276*1a4e3449SJack F Vogel  *  @lp_sym: symmetric pause bit in link partner advertisement
2277*1a4e3449SJack F Vogel  *  @lp_asm: asymmetric pause bit in link partner advertisement
2278*1a4e3449SJack F Vogel  *
2279*1a4e3449SJack F Vogel  *  Find the intersection between advertised settings and link partner's
2280*1a4e3449SJack F Vogel  *  advertised settings
2281*1a4e3449SJack F Vogel  **/
2282*1a4e3449SJack F Vogel static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
2283*1a4e3449SJack F Vogel 			      u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
2284*1a4e3449SJack F Vogel {
2285*1a4e3449SJack F Vogel 	if ((!(adv_reg)) ||  (!(lp_reg)))
2286*1a4e3449SJack F Vogel 		return IXGBE_ERR_FC_NOT_NEGOTIATED;
2287*1a4e3449SJack F Vogel 
2288*1a4e3449SJack F Vogel 	if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
22892969bf0eSJack F Vogel 		/*
22902969bf0eSJack F Vogel 		 * Now we need to check if the user selected Rx ONLY
22912969bf0eSJack F Vogel 		 * of pause frames.  In this case, we had to advertise
22922969bf0eSJack F Vogel 		 * FULL flow control because we could not advertise RX
22932969bf0eSJack F Vogel 		 * ONLY. Hence, we must now check to see if we need to
22942969bf0eSJack F Vogel 		 * turn OFF the TRANSMISSION of PAUSE frames.
22952969bf0eSJack F Vogel 		 */
22962969bf0eSJack F Vogel 		if (hw->fc.requested_mode == ixgbe_fc_full) {
22972969bf0eSJack F Vogel 			hw->fc.current_mode = ixgbe_fc_full;
22982969bf0eSJack F Vogel 			DEBUGOUT("Flow Control = FULL.\n");
22992969bf0eSJack F Vogel 		} else {
23002969bf0eSJack F Vogel 			hw->fc.current_mode = ixgbe_fc_rx_pause;
23012969bf0eSJack F Vogel 			DEBUGOUT("Flow Control=RX PAUSE frames only\n");
23022969bf0eSJack F Vogel 		}
2303*1a4e3449SJack F Vogel 	} else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
2304*1a4e3449SJack F Vogel 		   (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
23052969bf0eSJack F Vogel 		hw->fc.current_mode = ixgbe_fc_tx_pause;
23062969bf0eSJack F Vogel 		DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
2307*1a4e3449SJack F Vogel 	} else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
2308*1a4e3449SJack F Vogel 		   !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
23092969bf0eSJack F Vogel 		hw->fc.current_mode = ixgbe_fc_rx_pause;
23102969bf0eSJack F Vogel 		DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
23112969bf0eSJack F Vogel 	} else {
23122969bf0eSJack F Vogel 		hw->fc.current_mode = ixgbe_fc_none;
23132969bf0eSJack F Vogel 		DEBUGOUT("Flow Control = NONE.\n");
23142969bf0eSJack F Vogel 	}
2315*1a4e3449SJack F Vogel 	return IXGBE_SUCCESS;
23161b6e0dbaSJack F Vogel }
23171b6e0dbaSJack F Vogel 
23180ac6dfecSJack F Vogel /**
23190ac6dfecSJack F Vogel  *  ixgbe_setup_fc - Set up flow control
23200ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
23210ac6dfecSJack F Vogel  *
23220ac6dfecSJack F Vogel  *  Called at init time to set up flow control.
23230ac6dfecSJack F Vogel  **/
23240ac6dfecSJack F Vogel s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
23250ac6dfecSJack F Vogel {
23260ac6dfecSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
2327*1a4e3449SJack F Vogel 	u32 reg = 0, reg_bp = 0;
2328*1a4e3449SJack F Vogel 	u16 reg_cu = 0;
23290ac6dfecSJack F Vogel 
23302969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_setup_fc");
23312969bf0eSJack F Vogel 
23320ac6dfecSJack F Vogel 	/* Validate the packetbuf configuration */
23330ac6dfecSJack F Vogel 	if (packetbuf_num < 0 || packetbuf_num > 7) {
23340ac6dfecSJack F Vogel 		DEBUGOUT1("Invalid packet buffer number [%d], expected range is"
23350ac6dfecSJack F Vogel 		          " 0-7\n", packetbuf_num);
23360ac6dfecSJack F Vogel 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
23370ac6dfecSJack F Vogel 		goto out;
23380ac6dfecSJack F Vogel 	}
23390ac6dfecSJack F Vogel 
23400ac6dfecSJack F Vogel 	/*
23410ac6dfecSJack F Vogel 	 * Validate the water mark configuration.  Zero water marks are invalid
23420ac6dfecSJack F Vogel 	 * because it causes the controller to just blast out fc packets.
23430ac6dfecSJack F Vogel 	 */
23440ac6dfecSJack F Vogel 	if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
23450ac6dfecSJack F Vogel 		DEBUGOUT("Invalid water mark configuration\n");
23460ac6dfecSJack F Vogel 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
23470ac6dfecSJack F Vogel 		goto out;
23480ac6dfecSJack F Vogel 	}
23490ac6dfecSJack F Vogel 
23500ac6dfecSJack F Vogel 	/*
23510ac6dfecSJack F Vogel 	 * Validate the requested mode.  Strict IEEE mode does not allow
23520ac6dfecSJack F Vogel 	 * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
23530ac6dfecSJack F Vogel 	 */
23540ac6dfecSJack F Vogel 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
23550ac6dfecSJack F Vogel 		DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
23560ac6dfecSJack F Vogel 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
23570ac6dfecSJack F Vogel 		goto out;
23580ac6dfecSJack F Vogel 	}
23590ac6dfecSJack F Vogel 
23600ac6dfecSJack F Vogel 	/*
23610ac6dfecSJack F Vogel 	 * 10gig parts do not have a word in the EEPROM to determine the
23620ac6dfecSJack F Vogel 	 * default flow control setting, so we explicitly set it to full.
23630ac6dfecSJack F Vogel 	 */
23640ac6dfecSJack F Vogel 	if (hw->fc.requested_mode == ixgbe_fc_default)
23650ac6dfecSJack F Vogel 		hw->fc.requested_mode = ixgbe_fc_full;
23660ac6dfecSJack F Vogel 
23670ac6dfecSJack F Vogel 	/*
2368*1a4e3449SJack F Vogel 	 * Set up the 1G and 10G flow control advertisement registers so the
2369*1a4e3449SJack F Vogel 	 * HW will be able to do fc autoneg once the cable is plugged in.  If
2370*1a4e3449SJack F Vogel 	 * we link at 10G, the 1G advertisement is harmless and vice versa.
23710ac6dfecSJack F Vogel 	 */
2372*1a4e3449SJack F Vogel 
2373*1a4e3449SJack F Vogel 	switch (hw->phy.media_type) {
2374*1a4e3449SJack F Vogel 	case ixgbe_media_type_fiber:
2375*1a4e3449SJack F Vogel 	case ixgbe_media_type_backplane:
23760ac6dfecSJack F Vogel 		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
2377*1a4e3449SJack F Vogel 		reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
2378*1a4e3449SJack F Vogel 		break;
2379*1a4e3449SJack F Vogel 
2380*1a4e3449SJack F Vogel 	case ixgbe_media_type_copper:
2381*1a4e3449SJack F Vogel 		hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
2382*1a4e3449SJack F Vogel 					IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg_cu);
2383*1a4e3449SJack F Vogel 		break;
2384*1a4e3449SJack F Vogel 
2385*1a4e3449SJack F Vogel 	default:
2386*1a4e3449SJack F Vogel 		;
2387*1a4e3449SJack F Vogel 	}
23880ac6dfecSJack F Vogel 
23890ac6dfecSJack F Vogel 	/*
23900ac6dfecSJack F Vogel 	 * The possible values of fc.requested_mode are:
23910ac6dfecSJack F Vogel 	 * 0: Flow control is completely disabled
23920ac6dfecSJack F Vogel 	 * 1: Rx flow control is enabled (we can receive pause frames,
23930ac6dfecSJack F Vogel 	 *    but not send pause frames).
23940ac6dfecSJack F Vogel 	 * 2: Tx flow control is enabled (we can send pause frames but
23950ac6dfecSJack F Vogel 	 *    we do not support receiving pause frames).
23960ac6dfecSJack F Vogel 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
23970ac6dfecSJack F Vogel 	 * other: Invalid.
23980ac6dfecSJack F Vogel 	 */
23990ac6dfecSJack F Vogel 	switch (hw->fc.requested_mode) {
24000ac6dfecSJack F Vogel 	case ixgbe_fc_none:
24010ac6dfecSJack F Vogel 		/* Flow control completely disabled by software override. */
24020ac6dfecSJack F Vogel 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
2403*1a4e3449SJack F Vogel 		if (hw->phy.media_type == ixgbe_media_type_backplane)
2404*1a4e3449SJack F Vogel 			reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
2405*1a4e3449SJack F Vogel 				    IXGBE_AUTOC_ASM_PAUSE);
2406*1a4e3449SJack F Vogel 		else if (hw->phy.media_type == ixgbe_media_type_copper)
2407*1a4e3449SJack F Vogel 			reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
24080ac6dfecSJack F Vogel 		break;
24090ac6dfecSJack F Vogel 	case ixgbe_fc_rx_pause:
24100ac6dfecSJack F Vogel 		/*
24110ac6dfecSJack F Vogel 		 * Rx Flow control is enabled and Tx Flow control is
24120ac6dfecSJack F Vogel 		 * disabled by software override. Since there really
24130ac6dfecSJack F Vogel 		 * isn't a way to advertise that we are capable of RX
24140ac6dfecSJack F Vogel 		 * Pause ONLY, we will advertise that we support both
24150ac6dfecSJack F Vogel 		 * symmetric and asymmetric Rx PAUSE.  Later, we will
24160ac6dfecSJack F Vogel 		 * disable the adapter's ability to send PAUSE frames.
24170ac6dfecSJack F Vogel 		 */
24180ac6dfecSJack F Vogel 		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
2419*1a4e3449SJack F Vogel 		if (hw->phy.media_type == ixgbe_media_type_backplane)
2420*1a4e3449SJack F Vogel 			reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
2421*1a4e3449SJack F Vogel 				   IXGBE_AUTOC_ASM_PAUSE);
2422*1a4e3449SJack F Vogel 		else if (hw->phy.media_type == ixgbe_media_type_copper)
2423*1a4e3449SJack F Vogel 			reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
24240ac6dfecSJack F Vogel 		break;
24250ac6dfecSJack F Vogel 	case ixgbe_fc_tx_pause:
24260ac6dfecSJack F Vogel 		/*
24270ac6dfecSJack F Vogel 		 * Tx Flow control is enabled, and Rx Flow control is
24280ac6dfecSJack F Vogel 		 * disabled by software override.
24290ac6dfecSJack F Vogel 		 */
24300ac6dfecSJack F Vogel 		reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
24310ac6dfecSJack F Vogel 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
2432*1a4e3449SJack F Vogel 		if (hw->phy.media_type == ixgbe_media_type_backplane) {
2433*1a4e3449SJack F Vogel 			reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
2434*1a4e3449SJack F Vogel 			reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
2435*1a4e3449SJack F Vogel 		} else if (hw->phy.media_type == ixgbe_media_type_copper) {
2436*1a4e3449SJack F Vogel 			reg_cu |= (IXGBE_TAF_ASM_PAUSE);
2437*1a4e3449SJack F Vogel 			reg_cu &= ~(IXGBE_TAF_SYM_PAUSE);
2438*1a4e3449SJack F Vogel 		}
24390ac6dfecSJack F Vogel 		break;
24400ac6dfecSJack F Vogel 	case ixgbe_fc_full:
24410ac6dfecSJack F Vogel 		/* Flow control (both Rx and Tx) is enabled by SW override. */
24420ac6dfecSJack F Vogel 		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
2443*1a4e3449SJack F Vogel 		if (hw->phy.media_type == ixgbe_media_type_backplane)
2444*1a4e3449SJack F Vogel 			reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
2445*1a4e3449SJack F Vogel 				   IXGBE_AUTOC_ASM_PAUSE);
2446*1a4e3449SJack F Vogel 		else if (hw->phy.media_type == ixgbe_media_type_copper)
2447*1a4e3449SJack F Vogel 			reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
24480ac6dfecSJack F Vogel 		break;
24490ac6dfecSJack F Vogel 	default:
24500ac6dfecSJack F Vogel 		DEBUGOUT("Flow control param set incorrectly\n");
24512969bf0eSJack F Vogel 		ret_val = IXGBE_ERR_CONFIG;
24520ac6dfecSJack F Vogel 		goto out;
24530ac6dfecSJack F Vogel 		break;
24540ac6dfecSJack F Vogel 	}
24550ac6dfecSJack F Vogel 
2456*1a4e3449SJack F Vogel 	/*
2457*1a4e3449SJack F Vogel 	 * Enable auto-negotiation between the MAC & PHY;
2458*1a4e3449SJack F Vogel 	 * the MAC will advertise clause 37 flow control.
2459*1a4e3449SJack F Vogel 	 */
24600ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
24610ac6dfecSJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
24620ac6dfecSJack F Vogel 
24630ac6dfecSJack F Vogel 	/* Disable AN timeout */
24640ac6dfecSJack F Vogel 	if (hw->fc.strict_ieee)
24650ac6dfecSJack F Vogel 		reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
24660ac6dfecSJack F Vogel 
24670ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
24680ac6dfecSJack F Vogel 	DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
24690ac6dfecSJack F Vogel 
24702969bf0eSJack F Vogel 	/*
2471*1a4e3449SJack F Vogel 	 * AUTOC restart handles negotiation of 1G and 10G on backplane
2472*1a4e3449SJack F Vogel 	 * and copper. There is no need to set the PCS1GCTL register.
2473*1a4e3449SJack F Vogel 	 *
24742969bf0eSJack F Vogel 	 */
2475*1a4e3449SJack F Vogel 	if (hw->phy.media_type == ixgbe_media_type_backplane) {
2476*1a4e3449SJack F Vogel 		reg_bp |= IXGBE_AUTOC_AN_RESTART;
2477*1a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
2478*1a4e3449SJack F Vogel 	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
2479*1a4e3449SJack F Vogel 		    (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)) {
2480*1a4e3449SJack F Vogel 		hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
2481*1a4e3449SJack F Vogel 				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu);
24822969bf0eSJack F Vogel 	}
24832969bf0eSJack F Vogel 
2484*1a4e3449SJack F Vogel 	DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
24850ac6dfecSJack F Vogel out:
24860ac6dfecSJack F Vogel 	return ret_val;
24870ac6dfecSJack F Vogel }
24881b6e0dbaSJack F Vogel 
248913705f88SJack F Vogel /**
249013705f88SJack F Vogel  *  ixgbe_disable_pcie_master - Disable PCI-express master access
249113705f88SJack F Vogel  *  @hw: pointer to hardware structure
249213705f88SJack F Vogel  *
249313705f88SJack F Vogel  *  Disables PCI-Express master access and verifies there are no pending
249413705f88SJack F Vogel  *  requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
249513705f88SJack F Vogel  *  bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS
249613705f88SJack F Vogel  *  is returned signifying master requests disabled.
249713705f88SJack F Vogel  **/
249813705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
249913705f88SJack F Vogel {
25005b7f4cedSJack F Vogel 	u32 i;
25015b7f4cedSJack F Vogel 	u32 reg_val;
25025b7f4cedSJack F Vogel 	u32 number_of_queues;
2503c0014855SJack F Vogel 	s32 status = IXGBE_SUCCESS;
250413705f88SJack F Vogel 
25052969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_disable_pcie_master");
25062969bf0eSJack F Vogel 
2507c0014855SJack F Vogel 	/* Just jump out if bus mastering is already disabled */
2508c0014855SJack F Vogel 	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
2509c0014855SJack F Vogel 		goto out;
2510c0014855SJack F Vogel 
25115b7f4cedSJack F Vogel 	/* Disable the receive unit by stopping each queue */
25125b7f4cedSJack F Vogel 	number_of_queues = hw->mac.max_rx_queues;
25135b7f4cedSJack F Vogel 	for (i = 0; i < number_of_queues; i++) {
25145b7f4cedSJack F Vogel 		reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
25155b7f4cedSJack F Vogel 		if (reg_val & IXGBE_RXDCTL_ENABLE) {
25165b7f4cedSJack F Vogel 			reg_val &= ~IXGBE_RXDCTL_ENABLE;
25175b7f4cedSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
25185b7f4cedSJack F Vogel 		}
25195b7f4cedSJack F Vogel 	}
25205b7f4cedSJack F Vogel 
25215b7f4cedSJack F Vogel 	reg_val = IXGBE_READ_REG(hw, IXGBE_CTRL);
25225b7f4cedSJack F Vogel 	reg_val |= IXGBE_CTRL_GIO_DIS;
25235b7f4cedSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val);
252413705f88SJack F Vogel 
252513705f88SJack F Vogel 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
2526c0014855SJack F Vogel 		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
2527c0014855SJack F Vogel 			goto out;
252813705f88SJack F Vogel 		usec_delay(100);
252913705f88SJack F Vogel 	}
253013705f88SJack F Vogel 
2531c0014855SJack F Vogel 	DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
2532c0014855SJack F Vogel 	status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
2533c0014855SJack F Vogel 
2534c0014855SJack F Vogel 	/*
2535c0014855SJack F Vogel 	 * The GIO Master Disable bit didn't clear.  There are multiple reasons
2536c0014855SJack F Vogel 	 * for this listed in the datasheet 5.2.5.3.2 Master Disable, and they
2537c0014855SJack F Vogel 	 * all require a double reset to recover from.  Before proceeding, we
2538c0014855SJack F Vogel 	 * first wait a little more to try to ensure that, at a minimum, the
2539c0014855SJack F Vogel 	 * PCIe block has no transactions pending.
2540c0014855SJack F Vogel 	 */
2541c0014855SJack F Vogel 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
2542c0014855SJack F Vogel 		if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) &
2543c0014855SJack F Vogel 			IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
2544c0014855SJack F Vogel 			break;
2545c0014855SJack F Vogel 		usec_delay(100);
2546c0014855SJack F Vogel 	}
2547c0014855SJack F Vogel 
2548c0014855SJack F Vogel 	if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT)
2549c0014855SJack F Vogel 		DEBUGOUT("PCIe transaction pending bit also did not clear.\n");
2550c0014855SJack F Vogel 
2551c0014855SJack F Vogel 	/*
2552c0014855SJack F Vogel 	 * Two consecutive resets are required via CTRL.RST per datasheet
2553c0014855SJack F Vogel 	 * 5.2.5.3.2 Master Disable.  We set a flag to inform the reset routine
2554c0014855SJack F Vogel 	 * of this need.  The first reset prevents new master requests from
2555c0014855SJack F Vogel 	 * being issued by our device.  We then must wait 1usec for any
2556c0014855SJack F Vogel 	 * remaining completions from the PCIe bus to trickle in, and then reset
2557c0014855SJack F Vogel 	 * again to clear out any effects they may have had on our device.
2558c0014855SJack F Vogel 	 */
2559c0014855SJack F Vogel 	 hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
2560c0014855SJack F Vogel 
2561c0014855SJack F Vogel out:
256213705f88SJack F Vogel 	return status;
256313705f88SJack F Vogel }
256413705f88SJack F Vogel 
256513705f88SJack F Vogel 
256613705f88SJack F Vogel /**
25679ca4041bSJack F Vogel  *  ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
256813705f88SJack F Vogel  *  @hw: pointer to hardware structure
25699ca4041bSJack F Vogel  *  @mask: Mask to specify which semaphore to acquire
257013705f88SJack F Vogel  *
25719ca4041bSJack F Vogel  *  Acquires the SWFW semaphore thought the GSSR register for the specified
257213705f88SJack F Vogel  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
257313705f88SJack F Vogel  **/
257413705f88SJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
257513705f88SJack F Vogel {
257613705f88SJack F Vogel 	u32 gssr;
257713705f88SJack F Vogel 	u32 swmask = mask;
257813705f88SJack F Vogel 	u32 fwmask = mask << 5;
257913705f88SJack F Vogel 	s32 timeout = 200;
258013705f88SJack F Vogel 
25812969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_acquire_swfw_sync");
25822969bf0eSJack F Vogel 
258313705f88SJack F Vogel 	while (timeout) {
25840ac6dfecSJack F Vogel 		/*
25850ac6dfecSJack F Vogel 		 * SW EEPROM semaphore bit is used for access to all
25860ac6dfecSJack F Vogel 		 * SW_FW_SYNC/GSSR bits (not just EEPROM)
25870ac6dfecSJack F Vogel 		 */
258813705f88SJack F Vogel 		if (ixgbe_get_eeprom_semaphore(hw))
25892969bf0eSJack F Vogel 			return IXGBE_ERR_SWFW_SYNC;
259013705f88SJack F Vogel 
259113705f88SJack F Vogel 		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
259213705f88SJack F Vogel 		if (!(gssr & (fwmask | swmask)))
259313705f88SJack F Vogel 			break;
259413705f88SJack F Vogel 
259513705f88SJack F Vogel 		/*
259613705f88SJack F Vogel 		 * Firmware currently using resource (fwmask) or other software
259713705f88SJack F Vogel 		 * thread currently using resource (swmask)
259813705f88SJack F Vogel 		 */
259913705f88SJack F Vogel 		ixgbe_release_eeprom_semaphore(hw);
260013705f88SJack F Vogel 		msec_delay(5);
260113705f88SJack F Vogel 		timeout--;
260213705f88SJack F Vogel 	}
260313705f88SJack F Vogel 
260413705f88SJack F Vogel 	if (!timeout) {
26050ac6dfecSJack F Vogel 		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
26062969bf0eSJack F Vogel 		return IXGBE_ERR_SWFW_SYNC;
260713705f88SJack F Vogel 	}
260813705f88SJack F Vogel 
260913705f88SJack F Vogel 	gssr |= swmask;
261013705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
261113705f88SJack F Vogel 
261213705f88SJack F Vogel 	ixgbe_release_eeprom_semaphore(hw);
261313705f88SJack F Vogel 	return IXGBE_SUCCESS;
261413705f88SJack F Vogel }
261513705f88SJack F Vogel 
261613705f88SJack F Vogel /**
261713705f88SJack F Vogel  *  ixgbe_release_swfw_sync - Release SWFW semaphore
261813705f88SJack F Vogel  *  @hw: pointer to hardware structure
26199ca4041bSJack F Vogel  *  @mask: Mask to specify which semaphore to release
262013705f88SJack F Vogel  *
26219ca4041bSJack F Vogel  *  Releases the SWFW semaphore thought the GSSR register for the specified
262213705f88SJack F Vogel  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
262313705f88SJack F Vogel  **/
262413705f88SJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
262513705f88SJack F Vogel {
262613705f88SJack F Vogel 	u32 gssr;
262713705f88SJack F Vogel 	u32 swmask = mask;
262813705f88SJack F Vogel 
26292969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_release_swfw_sync");
26302969bf0eSJack F Vogel 
263113705f88SJack F Vogel 	ixgbe_get_eeprom_semaphore(hw);
263213705f88SJack F Vogel 
263313705f88SJack F Vogel 	gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
263413705f88SJack F Vogel 	gssr &= ~swmask;
263513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
263613705f88SJack F Vogel 
263713705f88SJack F Vogel 	ixgbe_release_eeprom_semaphore(hw);
26380ac6dfecSJack F Vogel }
26390ac6dfecSJack F Vogel 
26400ac6dfecSJack F Vogel /**
26410ac6dfecSJack F Vogel  *  ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
26420ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
26430ac6dfecSJack F Vogel  *  @regval: register value to write to RXCTRL
26440ac6dfecSJack F Vogel  *
26450ac6dfecSJack F Vogel  *  Enables the Rx DMA unit
26460ac6dfecSJack F Vogel  **/
26470ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval)
26480ac6dfecSJack F Vogel {
26492969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_enable_rx_dma_generic");
26502969bf0eSJack F Vogel 
26510ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
26520ac6dfecSJack F Vogel 
26530ac6dfecSJack F Vogel 	return IXGBE_SUCCESS;
26540ac6dfecSJack F Vogel }
26550ac6dfecSJack F Vogel 
26560ac6dfecSJack F Vogel /**
26570ac6dfecSJack F Vogel  *  ixgbe_blink_led_start_generic - Blink LED based on index.
26580ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
26590ac6dfecSJack F Vogel  *  @index: led number to blink
26600ac6dfecSJack F Vogel  **/
26610ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
26620ac6dfecSJack F Vogel {
26630ac6dfecSJack F Vogel 	ixgbe_link_speed speed = 0;
26640ac6dfecSJack F Vogel 	bool link_up = 0;
26650ac6dfecSJack F Vogel 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
26660ac6dfecSJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
26670ac6dfecSJack F Vogel 
26682969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_blink_led_start_generic");
26692969bf0eSJack F Vogel 
26700ac6dfecSJack F Vogel 	/*
26710ac6dfecSJack F Vogel 	 * Link must be up to auto-blink the LEDs;
26720ac6dfecSJack F Vogel 	 * Force it if link is down.
26730ac6dfecSJack F Vogel 	 */
26740ac6dfecSJack F Vogel 	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
26750ac6dfecSJack F Vogel 
26760ac6dfecSJack F Vogel 	if (!link_up) {
2677d8602bb9SJack F Vogel 		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
26780ac6dfecSJack F Vogel 		autoc_reg |= IXGBE_AUTOC_FLU;
26790ac6dfecSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
26800ac6dfecSJack F Vogel 		msec_delay(10);
26810ac6dfecSJack F Vogel 	}
26820ac6dfecSJack F Vogel 
26830ac6dfecSJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
26840ac6dfecSJack F Vogel 	led_reg |= IXGBE_LED_BLINK(index);
26850ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
26860ac6dfecSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
26870ac6dfecSJack F Vogel 
26880ac6dfecSJack F Vogel 	return IXGBE_SUCCESS;
26890ac6dfecSJack F Vogel }
26900ac6dfecSJack F Vogel 
26910ac6dfecSJack F Vogel /**
26920ac6dfecSJack F Vogel  *  ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
26930ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
26940ac6dfecSJack F Vogel  *  @index: led number to stop blinking
26950ac6dfecSJack F Vogel  **/
26960ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
26970ac6dfecSJack F Vogel {
26980ac6dfecSJack F Vogel 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
26990ac6dfecSJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
27000ac6dfecSJack F Vogel 
27012969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_blink_led_stop_generic");
27022969bf0eSJack F Vogel 
2703d8602bb9SJack F Vogel 
27040ac6dfecSJack F Vogel 	autoc_reg &= ~IXGBE_AUTOC_FLU;
27050ac6dfecSJack F Vogel 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
27060ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
27070ac6dfecSJack F Vogel 
27080ac6dfecSJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
27090ac6dfecSJack F Vogel 	led_reg &= ~IXGBE_LED_BLINK(index);
27100ac6dfecSJack F Vogel 	led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
27110ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
27120ac6dfecSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
27130ac6dfecSJack F Vogel 
27140ac6dfecSJack F Vogel 	return IXGBE_SUCCESS;
271513705f88SJack F Vogel }
271613705f88SJack F Vogel 
27172969bf0eSJack F Vogel /**
27182969bf0eSJack F Vogel  *  ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
27192969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
27202969bf0eSJack F Vogel  *  @san_mac_offset: SAN MAC address offset
27212969bf0eSJack F Vogel  *
27222969bf0eSJack F Vogel  *  This function will read the EEPROM location for the SAN MAC address
27232969bf0eSJack F Vogel  *  pointer, and returns the value at that location.  This is used in both
27242969bf0eSJack F Vogel  *  get and set mac_addr routines.
27252969bf0eSJack F Vogel  **/
27262969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
27272969bf0eSJack F Vogel                                         u16 *san_mac_offset)
27282969bf0eSJack F Vogel {
27292969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_san_mac_addr_offset");
27302969bf0eSJack F Vogel 
27312969bf0eSJack F Vogel 	/*
27322969bf0eSJack F Vogel 	 * First read the EEPROM pointer to see if the MAC addresses are
27332969bf0eSJack F Vogel 	 * available.
27342969bf0eSJack F Vogel 	 */
27352969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset);
27362969bf0eSJack F Vogel 
27372969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
27382969bf0eSJack F Vogel }
27392969bf0eSJack F Vogel 
27402969bf0eSJack F Vogel /**
27412969bf0eSJack F Vogel  *  ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM
27422969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
27432969bf0eSJack F Vogel  *  @san_mac_addr: SAN MAC address
27442969bf0eSJack F Vogel  *
27452969bf0eSJack F Vogel  *  Reads the SAN MAC address from the EEPROM, if it's available.  This is
27462969bf0eSJack F Vogel  *  per-port, so set_lan_id() must be called before reading the addresses.
27472969bf0eSJack F Vogel  *  set_lan_id() is called by identify_sfp(), but this cannot be relied
27482969bf0eSJack F Vogel  *  upon for non-SFP connections, so we must call it here.
27492969bf0eSJack F Vogel  **/
27502969bf0eSJack F Vogel s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
27512969bf0eSJack F Vogel {
27522969bf0eSJack F Vogel 	u16 san_mac_data, san_mac_offset;
27532969bf0eSJack F Vogel 	u8 i;
27542969bf0eSJack F Vogel 
27552969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_san_mac_addr_generic");
27562969bf0eSJack F Vogel 
27572969bf0eSJack F Vogel 	/*
27582969bf0eSJack F Vogel 	 * First read the EEPROM pointer to see if the MAC addresses are
27592969bf0eSJack F Vogel 	 * available.  If they're not, no point in calling set_lan_id() here.
27602969bf0eSJack F Vogel 	 */
27612969bf0eSJack F Vogel 	ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
27622969bf0eSJack F Vogel 
27632969bf0eSJack F Vogel 	if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
27642969bf0eSJack F Vogel 		/*
27652969bf0eSJack F Vogel 		 * No addresses available in this EEPROM.  It's not an
27662969bf0eSJack F Vogel 		 * error though, so just wipe the local address and return.
27672969bf0eSJack F Vogel 		 */
27682969bf0eSJack F Vogel 		for (i = 0; i < 6; i++)
27692969bf0eSJack F Vogel 			san_mac_addr[i] = 0xFF;
27702969bf0eSJack F Vogel 
27712969bf0eSJack F Vogel 		goto san_mac_addr_out;
27722969bf0eSJack F Vogel 	}
27732969bf0eSJack F Vogel 
27742969bf0eSJack F Vogel 	/* make sure we know which port we need to program */
27752969bf0eSJack F Vogel 	hw->mac.ops.set_lan_id(hw);
27762969bf0eSJack F Vogel 	/* apply the port offset to the address offset */
27772969bf0eSJack F Vogel 	(hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
27782969bf0eSJack F Vogel 	                 (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
27792969bf0eSJack F Vogel 	for (i = 0; i < 3; i++) {
27802969bf0eSJack F Vogel 		hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data);
27812969bf0eSJack F Vogel 		san_mac_addr[i * 2] = (u8)(san_mac_data);
27822969bf0eSJack F Vogel 		san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
27832969bf0eSJack F Vogel 		san_mac_offset++;
27842969bf0eSJack F Vogel 	}
27852969bf0eSJack F Vogel 
27862969bf0eSJack F Vogel san_mac_addr_out:
27872969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
27882969bf0eSJack F Vogel }
27892969bf0eSJack F Vogel 
27902969bf0eSJack F Vogel /**
27912969bf0eSJack F Vogel  *  ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM
27922969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
27932969bf0eSJack F Vogel  *  @san_mac_addr: SAN MAC address
27942969bf0eSJack F Vogel  *
27952969bf0eSJack F Vogel  *  Write a SAN MAC address to the EEPROM.
27962969bf0eSJack F Vogel  **/
27972969bf0eSJack F Vogel s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
27982969bf0eSJack F Vogel {
27992969bf0eSJack F Vogel 	s32 status = IXGBE_SUCCESS;
28002969bf0eSJack F Vogel 	u16 san_mac_data, san_mac_offset;
28012969bf0eSJack F Vogel 	u8 i;
28022969bf0eSJack F Vogel 
28032969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_san_mac_addr_generic");
28042969bf0eSJack F Vogel 
28052969bf0eSJack F Vogel 	/* Look for SAN mac address pointer.  If not defined, return */
28062969bf0eSJack F Vogel 	ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
28072969bf0eSJack F Vogel 
28082969bf0eSJack F Vogel 	if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
28092969bf0eSJack F Vogel 		status = IXGBE_ERR_NO_SAN_ADDR_PTR;
28102969bf0eSJack F Vogel 		goto san_mac_addr_out;
28112969bf0eSJack F Vogel 	}
28122969bf0eSJack F Vogel 
28132969bf0eSJack F Vogel 	/* Make sure we know which port we need to write */
28142969bf0eSJack F Vogel 	hw->mac.ops.set_lan_id(hw);
28152969bf0eSJack F Vogel 	/* Apply the port offset to the address offset */
28162969bf0eSJack F Vogel 	(hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
28172969bf0eSJack F Vogel 	                 (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
28182969bf0eSJack F Vogel 
28192969bf0eSJack F Vogel 	for (i = 0; i < 3; i++) {
28202969bf0eSJack F Vogel 		san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8);
28212969bf0eSJack F Vogel 		san_mac_data |= (u16)(san_mac_addr[i * 2]);
28222969bf0eSJack F Vogel 		hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data);
28232969bf0eSJack F Vogel 		san_mac_offset++;
28242969bf0eSJack F Vogel 	}
28252969bf0eSJack F Vogel 
28262969bf0eSJack F Vogel san_mac_addr_out:
28272969bf0eSJack F Vogel 	return status;
28282969bf0eSJack F Vogel }
28292969bf0eSJack F Vogel 
28302969bf0eSJack F Vogel /**
28312969bf0eSJack F Vogel  *  ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count
28322969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
28332969bf0eSJack F Vogel  *
28342969bf0eSJack F Vogel  *  Read PCIe configuration space, and get the MSI-X vector count from
28352969bf0eSJack F Vogel  *  the capabilities table.
28362969bf0eSJack F Vogel  **/
28372969bf0eSJack F Vogel u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
28382969bf0eSJack F Vogel {
28392969bf0eSJack F Vogel 	u32 msix_count = 64;
28402969bf0eSJack F Vogel 
28412969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_pcie_msix_count_generic");
28422969bf0eSJack F Vogel 	if (hw->mac.msix_vectors_from_pcie) {
28432969bf0eSJack F Vogel 		msix_count = IXGBE_READ_PCIE_WORD(hw,
28442969bf0eSJack F Vogel 		                                  IXGBE_PCIE_MSIX_82599_CAPS);
28452969bf0eSJack F Vogel 		msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
28462969bf0eSJack F Vogel 
28472969bf0eSJack F Vogel 		/* MSI-X count is zero-based in HW, so increment to give
28482969bf0eSJack F Vogel 		 * proper value */
28492969bf0eSJack F Vogel 		msix_count++;
28502969bf0eSJack F Vogel 	}
28512969bf0eSJack F Vogel 
28522969bf0eSJack F Vogel 	return msix_count;
28532969bf0eSJack F Vogel }
28542969bf0eSJack F Vogel 
28552969bf0eSJack F Vogel /**
28562969bf0eSJack F Vogel  *  ixgbe_insert_mac_addr_generic - Find a RAR for this mac address
28572969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
28582969bf0eSJack F Vogel  *  @addr: Address to put into receive address register
28592969bf0eSJack F Vogel  *  @vmdq: VMDq pool to assign
28602969bf0eSJack F Vogel  *
28612969bf0eSJack F Vogel  *  Puts an ethernet address into a receive address register, or
28622969bf0eSJack F Vogel  *  finds the rar that it is aleady in; adds to the pool list
28632969bf0eSJack F Vogel  **/
28642969bf0eSJack F Vogel s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
28652969bf0eSJack F Vogel {
28662969bf0eSJack F Vogel 	static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF;
28672969bf0eSJack F Vogel 	u32 first_empty_rar = NO_EMPTY_RAR_FOUND;
28682969bf0eSJack F Vogel 	u32 rar;
28692969bf0eSJack F Vogel 	u32 rar_low, rar_high;
28702969bf0eSJack F Vogel 	u32 addr_low, addr_high;
28712969bf0eSJack F Vogel 
28722969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_insert_mac_addr_generic");
28732969bf0eSJack F Vogel 
28742969bf0eSJack F Vogel 	/* swap bytes for HW little endian */
28752969bf0eSJack F Vogel 	addr_low  = addr[0] | (addr[1] << 8)
28762969bf0eSJack F Vogel 			    | (addr[2] << 16)
28772969bf0eSJack F Vogel 			    | (addr[3] << 24);
28782969bf0eSJack F Vogel 	addr_high = addr[4] | (addr[5] << 8);
28792969bf0eSJack F Vogel 
28802969bf0eSJack F Vogel 	/*
28812969bf0eSJack F Vogel 	 * Either find the mac_id in rar or find the first empty space.
28822969bf0eSJack F Vogel 	 * rar_highwater points to just after the highest currently used
28832969bf0eSJack F Vogel 	 * rar in order to shorten the search.  It grows when we add a new
28842969bf0eSJack F Vogel 	 * rar to the top.
28852969bf0eSJack F Vogel 	 */
28862969bf0eSJack F Vogel 	for (rar = 0; rar < hw->mac.rar_highwater; rar++) {
28872969bf0eSJack F Vogel 		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
28882969bf0eSJack F Vogel 
28892969bf0eSJack F Vogel 		if (((IXGBE_RAH_AV & rar_high) == 0)
28902969bf0eSJack F Vogel 		    && first_empty_rar == NO_EMPTY_RAR_FOUND) {
28912969bf0eSJack F Vogel 			first_empty_rar = rar;
28922969bf0eSJack F Vogel 		} else if ((rar_high & 0xFFFF) == addr_high) {
28932969bf0eSJack F Vogel 			rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar));
28942969bf0eSJack F Vogel 			if (rar_low == addr_low)
28952969bf0eSJack F Vogel 				break;    /* found it already in the rars */
28962969bf0eSJack F Vogel 		}
28972969bf0eSJack F Vogel 	}
28982969bf0eSJack F Vogel 
28992969bf0eSJack F Vogel 	if (rar < hw->mac.rar_highwater) {
29002969bf0eSJack F Vogel 		/* already there so just add to the pool bits */
29012969bf0eSJack F Vogel 		ixgbe_set_vmdq(hw, rar, vmdq);
29022969bf0eSJack F Vogel 	} else if (first_empty_rar != NO_EMPTY_RAR_FOUND) {
29032969bf0eSJack F Vogel 		/* stick it into first empty RAR slot we found */
29042969bf0eSJack F Vogel 		rar = first_empty_rar;
29052969bf0eSJack F Vogel 		ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
29062969bf0eSJack F Vogel 	} else if (rar == hw->mac.rar_highwater) {
29072969bf0eSJack F Vogel 		/* add it to the top of the list and inc the highwater mark */
29082969bf0eSJack F Vogel 		ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
29092969bf0eSJack F Vogel 		hw->mac.rar_highwater++;
29102969bf0eSJack F Vogel 	} else if (rar >= hw->mac.num_rar_entries) {
29112969bf0eSJack F Vogel 		return IXGBE_ERR_INVALID_MAC_ADDR;
29122969bf0eSJack F Vogel 	}
29132969bf0eSJack F Vogel 
29142969bf0eSJack F Vogel 	/*
29152969bf0eSJack F Vogel 	 * If we found rar[0], make sure the default pool bit (we use pool 0)
29162969bf0eSJack F Vogel 	 * remains cleared to be sure default pool packets will get delivered
29172969bf0eSJack F Vogel 	 */
29182969bf0eSJack F Vogel 	if (rar == 0)
29192969bf0eSJack F Vogel 		ixgbe_clear_vmdq(hw, rar, 0);
29202969bf0eSJack F Vogel 
29212969bf0eSJack F Vogel 	return rar;
29222969bf0eSJack F Vogel }
29232969bf0eSJack F Vogel 
29242969bf0eSJack F Vogel /**
29252969bf0eSJack F Vogel  *  ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address
29262969bf0eSJack F Vogel  *  @hw: pointer to hardware struct
29272969bf0eSJack F Vogel  *  @rar: receive address register index to disassociate
29282969bf0eSJack F Vogel  *  @vmdq: VMDq pool index to remove from the rar
29292969bf0eSJack F Vogel  **/
29302969bf0eSJack F Vogel s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
29312969bf0eSJack F Vogel {
29322969bf0eSJack F Vogel 	u32 mpsar_lo, mpsar_hi;
29332969bf0eSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
29342969bf0eSJack F Vogel 
29352969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_clear_vmdq_generic");
29362969bf0eSJack F Vogel 
2937*1a4e3449SJack F Vogel 	/* Make sure we are using a valid rar index range */
2938*1a4e3449SJack F Vogel 	if (rar >= rar_entries) {
2939*1a4e3449SJack F Vogel 		DEBUGOUT1("RAR index %d is out of range.\n", rar);
2940*1a4e3449SJack F Vogel 		return IXGBE_ERR_INVALID_ARGUMENT;
2941*1a4e3449SJack F Vogel 	}
2942*1a4e3449SJack F Vogel 
29432969bf0eSJack F Vogel 	mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
29442969bf0eSJack F Vogel 	mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
29452969bf0eSJack F Vogel 
29462969bf0eSJack F Vogel 	if (!mpsar_lo && !mpsar_hi)
29472969bf0eSJack F Vogel 		goto done;
29482969bf0eSJack F Vogel 
29492969bf0eSJack F Vogel 	if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
29502969bf0eSJack F Vogel 		if (mpsar_lo) {
29512969bf0eSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
29522969bf0eSJack F Vogel 			mpsar_lo = 0;
29532969bf0eSJack F Vogel 		}
29542969bf0eSJack F Vogel 		if (mpsar_hi) {
29552969bf0eSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
29562969bf0eSJack F Vogel 			mpsar_hi = 0;
29572969bf0eSJack F Vogel 		}
29582969bf0eSJack F Vogel 	} else if (vmdq < 32) {
29592969bf0eSJack F Vogel 		mpsar_lo &= ~(1 << vmdq);
29602969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
29612969bf0eSJack F Vogel 	} else {
29622969bf0eSJack F Vogel 		mpsar_hi &= ~(1 << (vmdq - 32));
29632969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
29642969bf0eSJack F Vogel 	}
29652969bf0eSJack F Vogel 
29662969bf0eSJack F Vogel 	/* was that the last pool using this rar? */
29672969bf0eSJack F Vogel 	if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
29682969bf0eSJack F Vogel 		hw->mac.ops.clear_rar(hw, rar);
29692969bf0eSJack F Vogel done:
29702969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
29712969bf0eSJack F Vogel }
29722969bf0eSJack F Vogel 
29732969bf0eSJack F Vogel /**
29742969bf0eSJack F Vogel  *  ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address
29752969bf0eSJack F Vogel  *  @hw: pointer to hardware struct
29762969bf0eSJack F Vogel  *  @rar: receive address register index to associate with a VMDq index
29772969bf0eSJack F Vogel  *  @vmdq: VMDq pool index
29782969bf0eSJack F Vogel  **/
29792969bf0eSJack F Vogel s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
29802969bf0eSJack F Vogel {
29812969bf0eSJack F Vogel 	u32 mpsar;
29822969bf0eSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
29832969bf0eSJack F Vogel 
29842969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_vmdq_generic");
29852969bf0eSJack F Vogel 
2986*1a4e3449SJack F Vogel 	/* Make sure we are using a valid rar index range */
2987*1a4e3449SJack F Vogel 	if (rar >= rar_entries) {
2988*1a4e3449SJack F Vogel 		DEBUGOUT1("RAR index %d is out of range.\n", rar);
2989*1a4e3449SJack F Vogel 		return IXGBE_ERR_INVALID_ARGUMENT;
2990*1a4e3449SJack F Vogel 	}
2991*1a4e3449SJack F Vogel 
29922969bf0eSJack F Vogel 	if (vmdq < 32) {
29932969bf0eSJack F Vogel 		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
29942969bf0eSJack F Vogel 		mpsar |= 1 << vmdq;
29952969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
29962969bf0eSJack F Vogel 	} else {
29972969bf0eSJack F Vogel 		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
29982969bf0eSJack F Vogel 		mpsar |= 1 << (vmdq - 32);
29992969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
30002969bf0eSJack F Vogel 	}
30012969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
30022969bf0eSJack F Vogel }
30032969bf0eSJack F Vogel 
30042969bf0eSJack F Vogel /**
30052969bf0eSJack F Vogel  *  ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array
30062969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
30072969bf0eSJack F Vogel  **/
30082969bf0eSJack F Vogel s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
30092969bf0eSJack F Vogel {
30102969bf0eSJack F Vogel 	int i;
30112969bf0eSJack F Vogel 
30122969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_uta_tables_generic");
30132969bf0eSJack F Vogel 	DEBUGOUT(" Clearing UTA\n");
30142969bf0eSJack F Vogel 
30152969bf0eSJack F Vogel 	for (i = 0; i < 128; i++)
30162969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
30172969bf0eSJack F Vogel 
30182969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
30192969bf0eSJack F Vogel }
30202969bf0eSJack F Vogel 
30212969bf0eSJack F Vogel /**
30222969bf0eSJack F Vogel  *  ixgbe_find_vlvf_slot - find the vlanid or the first empty slot
30232969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
30242969bf0eSJack F Vogel  *  @vlan: VLAN id to write to VLAN filter
30252969bf0eSJack F Vogel  *
30262969bf0eSJack F Vogel  *  return the VLVF index where this VLAN id should be placed
30272969bf0eSJack F Vogel  *
30282969bf0eSJack F Vogel  **/
30292969bf0eSJack F Vogel s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
30302969bf0eSJack F Vogel {
30312969bf0eSJack F Vogel 	u32 bits = 0;
30322969bf0eSJack F Vogel 	u32 first_empty_slot = 0;
30332969bf0eSJack F Vogel 	s32 regindex;
30342969bf0eSJack F Vogel 
3035c0014855SJack F Vogel 	/* short cut the special case */
3036c0014855SJack F Vogel 	if (vlan == 0)
3037c0014855SJack F Vogel 		return 0;
3038c0014855SJack F Vogel 
30392969bf0eSJack F Vogel 	/*
30402969bf0eSJack F Vogel 	  * Search for the vlan id in the VLVF entries. Save off the first empty
30412969bf0eSJack F Vogel 	  * slot found along the way
30422969bf0eSJack F Vogel 	  */
30432969bf0eSJack F Vogel 	for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
30442969bf0eSJack F Vogel 		bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
30452969bf0eSJack F Vogel 		if (!bits && !(first_empty_slot))
30462969bf0eSJack F Vogel 			first_empty_slot = regindex;
30472969bf0eSJack F Vogel 		else if ((bits & 0x0FFF) == vlan)
30482969bf0eSJack F Vogel 			break;
30492969bf0eSJack F Vogel 	}
30502969bf0eSJack F Vogel 
30512969bf0eSJack F Vogel 	/*
30522969bf0eSJack F Vogel 	  * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan
30532969bf0eSJack F Vogel 	  * in the VLVF. Else use the first empty VLVF register for this
30542969bf0eSJack F Vogel 	  * vlan id.
30552969bf0eSJack F Vogel 	  */
30562969bf0eSJack F Vogel 	if (regindex >= IXGBE_VLVF_ENTRIES) {
30572969bf0eSJack F Vogel 		if (first_empty_slot)
30582969bf0eSJack F Vogel 			regindex = first_empty_slot;
30592969bf0eSJack F Vogel 		else {
30602969bf0eSJack F Vogel 			DEBUGOUT("No space in VLVF.\n");
3061c0014855SJack F Vogel 			regindex = IXGBE_ERR_NO_SPACE;
30622969bf0eSJack F Vogel 		}
30632969bf0eSJack F Vogel 	}
30642969bf0eSJack F Vogel 
30652969bf0eSJack F Vogel 	return regindex;
30662969bf0eSJack F Vogel }
30672969bf0eSJack F Vogel 
30682969bf0eSJack F Vogel /**
30692969bf0eSJack F Vogel  *  ixgbe_set_vfta_generic - Set VLAN filter table
30702969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
30712969bf0eSJack F Vogel  *  @vlan: VLAN id to write to VLAN filter
30722969bf0eSJack F Vogel  *  @vind: VMDq output index that maps queue to VLAN id in VFVFB
30732969bf0eSJack F Vogel  *  @vlan_on: boolean flag to turn on/off VLAN in VFVF
30742969bf0eSJack F Vogel  *
30752969bf0eSJack F Vogel  *  Turn on/off specified VLAN in the VLAN filter table.
30762969bf0eSJack F Vogel  **/
30772969bf0eSJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
30782969bf0eSJack F Vogel                            bool vlan_on)
30792969bf0eSJack F Vogel {
30802969bf0eSJack F Vogel 	s32 regindex;
30812969bf0eSJack F Vogel 	u32 bitindex;
3082c0014855SJack F Vogel 	u32 vfta;
30832969bf0eSJack F Vogel 	u32 bits;
30842969bf0eSJack F Vogel 	u32 vt;
3085c0014855SJack F Vogel 	u32 targetbit;
3086c0014855SJack F Vogel 	bool vfta_changed = FALSE;
30872969bf0eSJack F Vogel 
30882969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_vfta_generic");
30892969bf0eSJack F Vogel 
30902969bf0eSJack F Vogel 	if (vlan > 4095)
30912969bf0eSJack F Vogel 		return IXGBE_ERR_PARAM;
30922969bf0eSJack F Vogel 
30932969bf0eSJack F Vogel 	/*
30942969bf0eSJack F Vogel 	 * this is a 2 part operation - first the VFTA, then the
30952969bf0eSJack F Vogel 	 * VLVF and VLVFB if VT Mode is set
3096c0014855SJack F Vogel 	 * We don't write the VFTA until we know the VLVF part succeeded.
30972969bf0eSJack F Vogel 	 */
30982969bf0eSJack F Vogel 
30992969bf0eSJack F Vogel 	/* Part 1
31002969bf0eSJack F Vogel 	 * The VFTA is a bitstring made up of 128 32-bit registers
31012969bf0eSJack F Vogel 	 * that enable the particular VLAN id, much like the MTA:
31022969bf0eSJack F Vogel 	 *    bits[11-5]: which register
31032969bf0eSJack F Vogel 	 *    bits[4-0]:  which bit in the register
31042969bf0eSJack F Vogel 	 */
31052969bf0eSJack F Vogel 	regindex = (vlan >> 5) & 0x7F;
31062969bf0eSJack F Vogel 	bitindex = vlan & 0x1F;
3107c0014855SJack F Vogel 	targetbit = (1 << bitindex);
3108c0014855SJack F Vogel 	vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
31092969bf0eSJack F Vogel 
3110c0014855SJack F Vogel 	if (vlan_on) {
3111c0014855SJack F Vogel 		if (!(vfta & targetbit)) {
3112c0014855SJack F Vogel 			vfta |= targetbit;
3113c0014855SJack F Vogel 			vfta_changed = TRUE;
3114c0014855SJack F Vogel 		}
3115c0014855SJack F Vogel 	} else {
3116c0014855SJack F Vogel 		if ((vfta & targetbit)) {
3117c0014855SJack F Vogel 			vfta &= ~targetbit;
3118c0014855SJack F Vogel 			vfta_changed = TRUE;
3119c0014855SJack F Vogel 		}
3120c0014855SJack F Vogel 	}
31212969bf0eSJack F Vogel 
31222969bf0eSJack F Vogel 	/* Part 2
31232969bf0eSJack F Vogel 	 * If VT Mode is set
31242969bf0eSJack F Vogel 	 *   Either vlan_on
31252969bf0eSJack F Vogel 	 *     make sure the vlan is in VLVF
31262969bf0eSJack F Vogel 	 *     set the vind bit in the matching VLVFB
31272969bf0eSJack F Vogel 	 *   Or !vlan_on
31282969bf0eSJack F Vogel 	 *     clear the pool bit and possibly the vind
31292969bf0eSJack F Vogel 	 */
31302969bf0eSJack F Vogel 	vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
31312969bf0eSJack F Vogel 	if (vt & IXGBE_VT_CTL_VT_ENABLE) {
3132c0014855SJack F Vogel 		s32 vlvf_index;
3133c0014855SJack F Vogel 
3134c0014855SJack F Vogel 		vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
3135c0014855SJack F Vogel 		if (vlvf_index < 0)
3136c0014855SJack F Vogel 			return vlvf_index;
31372969bf0eSJack F Vogel 
31382969bf0eSJack F Vogel 		if (vlan_on) {
31392969bf0eSJack F Vogel 			/* set the pool bit */
31402969bf0eSJack F Vogel 			if (vind < 32) {
31412969bf0eSJack F Vogel 				bits = IXGBE_READ_REG(hw,
3142c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2));
31432969bf0eSJack F Vogel 				bits |= (1 << vind);
31442969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw,
3145c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2),
31462969bf0eSJack F Vogel 						bits);
31472969bf0eSJack F Vogel 			} else {
31482969bf0eSJack F Vogel 				bits = IXGBE_READ_REG(hw,
3149c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1));
3150c0014855SJack F Vogel 				bits |= (1 << (vind-32));
31512969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw,
3152c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1),
31532969bf0eSJack F Vogel 						bits);
31542969bf0eSJack F Vogel 			}
31552969bf0eSJack F Vogel 		} else {
31562969bf0eSJack F Vogel 			/* clear the pool bit */
31572969bf0eSJack F Vogel 			if (vind < 32) {
31582969bf0eSJack F Vogel 				bits = IXGBE_READ_REG(hw,
3159c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2));
31602969bf0eSJack F Vogel 				bits &= ~(1 << vind);
31612969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw,
3162c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2),
31632969bf0eSJack F Vogel 						bits);
31642969bf0eSJack F Vogel 				bits |= IXGBE_READ_REG(hw,
3165c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1));
31662969bf0eSJack F Vogel 			} else {
31672969bf0eSJack F Vogel 				bits = IXGBE_READ_REG(hw,
3168c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1));
3169c0014855SJack F Vogel 				bits &= ~(1 << (vind-32));
31702969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw,
3171c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1),
31722969bf0eSJack F Vogel 						bits);
31732969bf0eSJack F Vogel 				bits |= IXGBE_READ_REG(hw,
3174c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2));
31752969bf0eSJack F Vogel 			}
31762969bf0eSJack F Vogel 		}
31772969bf0eSJack F Vogel 
3178c0014855SJack F Vogel 		/*
3179c0014855SJack F Vogel 		 * If there are still bits set in the VLVFB registers
3180c0014855SJack F Vogel 		 * for the VLAN ID indicated we need to see if the
3181c0014855SJack F Vogel 		 * caller is requesting that we clear the VFTA entry bit.
3182c0014855SJack F Vogel 		 * If the caller has requested that we clear the VFTA
3183c0014855SJack F Vogel 		 * entry bit but there are still pools/VFs using this VLAN
3184c0014855SJack F Vogel 		 * ID entry then ignore the request.  We're not worried
3185c0014855SJack F Vogel 		 * about the case where we're turning the VFTA VLAN ID
3186c0014855SJack F Vogel 		 * entry bit on, only when requested to turn it off as
3187c0014855SJack F Vogel 		 * there may be multiple pools and/or VFs using the
3188c0014855SJack F Vogel 		 * VLAN ID entry.  In that case we cannot clear the
3189c0014855SJack F Vogel 		 * VFTA bit until all pools/VFs using that VLAN ID have also
3190c0014855SJack F Vogel 		 * been cleared.  This will be indicated by "bits" being
3191c0014855SJack F Vogel 		 * zero.
3192c0014855SJack F Vogel 		 */
3193c0014855SJack F Vogel 		if (bits) {
3194c0014855SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index),
31952969bf0eSJack F Vogel 					(IXGBE_VLVF_VIEN | vlan));
3196c0014855SJack F Vogel 			if (!vlan_on) {
3197c0014855SJack F Vogel 				/* someone wants to clear the vfta entry
3198c0014855SJack F Vogel 				 * but some pools/VFs are still using it.
3199c0014855SJack F Vogel 				 * Ignore it. */
3200c0014855SJack F Vogel 				vfta_changed = FALSE;
32012969bf0eSJack F Vogel 			}
3202c0014855SJack F Vogel 		}
3203c0014855SJack F Vogel 		else
3204c0014855SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
3205c0014855SJack F Vogel 	}
3206c0014855SJack F Vogel 
3207c0014855SJack F Vogel 	if (vfta_changed)
3208c0014855SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
3209c0014855SJack F Vogel 
32102969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
32112969bf0eSJack F Vogel }
32122969bf0eSJack F Vogel 
32132969bf0eSJack F Vogel /**
32142969bf0eSJack F Vogel  *  ixgbe_clear_vfta_generic - Clear VLAN filter table
32152969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
32162969bf0eSJack F Vogel  *
32172969bf0eSJack F Vogel  *  Clears the VLAN filer table, and the VMDq index associated with the filter
32182969bf0eSJack F Vogel  **/
32192969bf0eSJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
32202969bf0eSJack F Vogel {
32212969bf0eSJack F Vogel 	u32 offset;
32222969bf0eSJack F Vogel 
32232969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_clear_vfta_generic");
32242969bf0eSJack F Vogel 
32252969bf0eSJack F Vogel 	for (offset = 0; offset < hw->mac.vft_size; offset++)
32262969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
32272969bf0eSJack F Vogel 
32282969bf0eSJack F Vogel 	for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
32292969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
32302969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0);
32312969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0);
32322969bf0eSJack F Vogel 	}
32332969bf0eSJack F Vogel 
32342969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
32352969bf0eSJack F Vogel }
32362969bf0eSJack F Vogel 
32372969bf0eSJack F Vogel /**
32382969bf0eSJack F Vogel  *  ixgbe_check_mac_link_generic - Determine link and speed status
32392969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
32402969bf0eSJack F Vogel  *  @speed: pointer to link speed
32412969bf0eSJack F Vogel  *  @link_up: TRUE when link is up
32422969bf0eSJack F Vogel  *  @link_up_wait_to_complete: bool used to wait for link up or not
32432969bf0eSJack F Vogel  *
32442969bf0eSJack F Vogel  *  Reads the links register to determine if link is up and the current speed
32452969bf0eSJack F Vogel  **/
32462969bf0eSJack F Vogel s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
32472969bf0eSJack F Vogel                                  bool *link_up, bool link_up_wait_to_complete)
32482969bf0eSJack F Vogel {
3249c0014855SJack F Vogel 	u32 links_reg, links_orig;
32502969bf0eSJack F Vogel 	u32 i;
32512969bf0eSJack F Vogel 
32522969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_check_mac_link_generic");
32532969bf0eSJack F Vogel 
3254c0014855SJack F Vogel 	/* clear the old state */
3255c0014855SJack F Vogel 	links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
3256c0014855SJack F Vogel 
32572969bf0eSJack F Vogel 	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
3258c0014855SJack F Vogel 
3259c0014855SJack F Vogel 	if (links_orig != links_reg) {
3260c0014855SJack F Vogel 		DEBUGOUT2("LINKS changed from %08X to %08X\n",
3261c0014855SJack F Vogel 		          links_orig, links_reg);
3262c0014855SJack F Vogel 	}
3263c0014855SJack F Vogel 
32642969bf0eSJack F Vogel 	if (link_up_wait_to_complete) {
32652969bf0eSJack F Vogel 		for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
32662969bf0eSJack F Vogel 			if (links_reg & IXGBE_LINKS_UP) {
32672969bf0eSJack F Vogel 				*link_up = TRUE;
32682969bf0eSJack F Vogel 				break;
32692969bf0eSJack F Vogel 			} else {
32702969bf0eSJack F Vogel 				*link_up = FALSE;
32712969bf0eSJack F Vogel 			}
32722969bf0eSJack F Vogel 			msec_delay(100);
32732969bf0eSJack F Vogel 			links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
32742969bf0eSJack F Vogel 		}
32752969bf0eSJack F Vogel 	} else {
32762969bf0eSJack F Vogel 		if (links_reg & IXGBE_LINKS_UP)
32772969bf0eSJack F Vogel 			*link_up = TRUE;
32782969bf0eSJack F Vogel 		else
32792969bf0eSJack F Vogel 			*link_up = FALSE;
32802969bf0eSJack F Vogel 	}
32812969bf0eSJack F Vogel 
32822969bf0eSJack F Vogel 	if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
32832969bf0eSJack F Vogel 	    IXGBE_LINKS_SPEED_10G_82599)
32842969bf0eSJack F Vogel 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
32852969bf0eSJack F Vogel 	else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
32862969bf0eSJack F Vogel 	         IXGBE_LINKS_SPEED_1G_82599)
32872969bf0eSJack F Vogel 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
3288*1a4e3449SJack F Vogel 	else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
3289*1a4e3449SJack F Vogel 	         IXGBE_LINKS_SPEED_100_82599)
32902969bf0eSJack F Vogel 		*speed = IXGBE_LINK_SPEED_100_FULL;
3291*1a4e3449SJack F Vogel 	else
3292*1a4e3449SJack F Vogel 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
32932969bf0eSJack F Vogel 
32942969bf0eSJack F Vogel 	/* if link is down, zero out the current_mode */
32952969bf0eSJack F Vogel 	if (*link_up == FALSE) {
32962969bf0eSJack F Vogel 		hw->fc.current_mode = ixgbe_fc_none;
32972969bf0eSJack F Vogel 		hw->fc.fc_was_autonegged = FALSE;
32982969bf0eSJack F Vogel 	}
32992969bf0eSJack F Vogel 
33002969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
33012969bf0eSJack F Vogel }
33022969bf0eSJack F Vogel 
33032969bf0eSJack F Vogel /**
33042969bf0eSJack F Vogel  *  ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from
33052969bf0eSJack F Vogel  *  the EEPROM
33062969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
33072969bf0eSJack F Vogel  *  @wwnn_prefix: the alternative WWNN prefix
33082969bf0eSJack F Vogel  *  @wwpn_prefix: the alternative WWPN prefix
33092969bf0eSJack F Vogel  *
33102969bf0eSJack F Vogel  *  This function will read the EEPROM from the alternative SAN MAC address
33112969bf0eSJack F Vogel  *  block to check the support for the alternative WWNN/WWPN prefix support.
33122969bf0eSJack F Vogel  **/
33132969bf0eSJack F Vogel s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
33142969bf0eSJack F Vogel                                  u16 *wwpn_prefix)
33152969bf0eSJack F Vogel {
33162969bf0eSJack F Vogel 	u16 offset, caps;
33172969bf0eSJack F Vogel 	u16 alt_san_mac_blk_offset;
33182969bf0eSJack F Vogel 
33192969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_wwn_prefix_generic");
33202969bf0eSJack F Vogel 
33212969bf0eSJack F Vogel 	/* clear output first */
33222969bf0eSJack F Vogel 	*wwnn_prefix = 0xFFFF;
33232969bf0eSJack F Vogel 	*wwpn_prefix = 0xFFFF;
33242969bf0eSJack F Vogel 
33252969bf0eSJack F Vogel 	/* check if alternative SAN MAC is supported */
33262969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR,
33272969bf0eSJack F Vogel 	                    &alt_san_mac_blk_offset);
33282969bf0eSJack F Vogel 
33292969bf0eSJack F Vogel 	if ((alt_san_mac_blk_offset == 0) ||
33302969bf0eSJack F Vogel 	    (alt_san_mac_blk_offset == 0xFFFF))
33312969bf0eSJack F Vogel 		goto wwn_prefix_out;
33322969bf0eSJack F Vogel 
33332969bf0eSJack F Vogel 	/* check capability in alternative san mac address block */
33342969bf0eSJack F Vogel 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
33352969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, offset, &caps);
33362969bf0eSJack F Vogel 	if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
33372969bf0eSJack F Vogel 		goto wwn_prefix_out;
33382969bf0eSJack F Vogel 
33392969bf0eSJack F Vogel 	/* get the corresponding prefix for WWNN/WWPN */
33402969bf0eSJack F Vogel 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
33412969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, offset, wwnn_prefix);
33422969bf0eSJack F Vogel 
33432969bf0eSJack F Vogel 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
33442969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, offset, wwpn_prefix);
33452969bf0eSJack F Vogel 
33462969bf0eSJack F Vogel wwn_prefix_out:
33472969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
33482969bf0eSJack F Vogel }
3349*1a4e3449SJack F Vogel 
3350*1a4e3449SJack F Vogel /**
3351*1a4e3449SJack F Vogel  *  ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM
3352*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
3353*1a4e3449SJack F Vogel  *  @bs: the fcoe boot status
3354*1a4e3449SJack F Vogel  *
3355*1a4e3449SJack F Vogel  *  This function will read the FCOE boot status from the iSCSI FCOE block
3356*1a4e3449SJack F Vogel  **/
3357*1a4e3449SJack F Vogel s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs)
3358*1a4e3449SJack F Vogel {
3359*1a4e3449SJack F Vogel 	u16 offset, caps, flags;
3360*1a4e3449SJack F Vogel 	s32 status;
3361*1a4e3449SJack F Vogel 
3362*1a4e3449SJack F Vogel 	DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic");
3363*1a4e3449SJack F Vogel 
3364*1a4e3449SJack F Vogel 	/* clear output first */
3365*1a4e3449SJack F Vogel 	*bs = ixgbe_fcoe_bootstatus_unavailable;
3366*1a4e3449SJack F Vogel 
3367*1a4e3449SJack F Vogel 	/* check if FCOE IBA block is present */
3368*1a4e3449SJack F Vogel 	offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR;
3369*1a4e3449SJack F Vogel 	status = hw->eeprom.ops.read(hw, offset, &caps);
3370*1a4e3449SJack F Vogel 	if (status != IXGBE_SUCCESS)
3371*1a4e3449SJack F Vogel 		goto out;
3372*1a4e3449SJack F Vogel 
3373*1a4e3449SJack F Vogel 	if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE))
3374*1a4e3449SJack F Vogel 		goto out;
3375*1a4e3449SJack F Vogel 
3376*1a4e3449SJack F Vogel 	/* check if iSCSI FCOE block is populated */
3377*1a4e3449SJack F Vogel 	status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset);
3378*1a4e3449SJack F Vogel 	if (status != IXGBE_SUCCESS)
3379*1a4e3449SJack F Vogel 		goto out;
3380*1a4e3449SJack F Vogel 
3381*1a4e3449SJack F Vogel 	if ((offset == 0) || (offset == 0xFFFF))
3382*1a4e3449SJack F Vogel 		goto out;
3383*1a4e3449SJack F Vogel 
3384*1a4e3449SJack F Vogel 	/* read fcoe flags in iSCSI FCOE block */
3385*1a4e3449SJack F Vogel 	offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET;
3386*1a4e3449SJack F Vogel 	status = hw->eeprom.ops.read(hw, offset, &flags);
3387*1a4e3449SJack F Vogel 	if (status != IXGBE_SUCCESS)
3388*1a4e3449SJack F Vogel 		goto out;
3389*1a4e3449SJack F Vogel 
3390*1a4e3449SJack F Vogel 	if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE)
3391*1a4e3449SJack F Vogel 		*bs = ixgbe_fcoe_bootstatus_enabled;
3392*1a4e3449SJack F Vogel 	else
3393*1a4e3449SJack F Vogel 		*bs = ixgbe_fcoe_bootstatus_disabled;
3394*1a4e3449SJack F Vogel 
3395*1a4e3449SJack F Vogel out:
3396*1a4e3449SJack F Vogel 	return status;
3397*1a4e3449SJack F Vogel }
3398*1a4e3449SJack F Vogel 
3399*1a4e3449SJack F Vogel /**
3400*1a4e3449SJack F Vogel  *  ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
3401*1a4e3449SJack F Vogel  *  control
3402*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
3403*1a4e3449SJack F Vogel  *
3404*1a4e3449SJack F Vogel  *  There are several phys that do not support autoneg flow control. This
3405*1a4e3449SJack F Vogel  *  function check the device id to see if the associated phy supports
3406*1a4e3449SJack F Vogel  *  autoneg flow control.
3407*1a4e3449SJack F Vogel  **/
3408*1a4e3449SJack F Vogel static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
3409*1a4e3449SJack F Vogel {
3410*1a4e3449SJack F Vogel 
3411*1a4e3449SJack F Vogel 	DEBUGFUNC("ixgbe_device_supports_autoneg_fc");
3412*1a4e3449SJack F Vogel 
3413*1a4e3449SJack F Vogel 	switch (hw->device_id) {
3414*1a4e3449SJack F Vogel 	case IXGBE_DEV_ID_82599_T3_LOM:
3415*1a4e3449SJack F Vogel 		return IXGBE_SUCCESS;
3416*1a4e3449SJack F Vogel 	default:
3417*1a4e3449SJack F Vogel 		return IXGBE_ERR_FC_NOT_SUPPORTED;
3418*1a4e3449SJack F Vogel 	}
3419*1a4e3449SJack F Vogel }
3420*1a4e3449SJack F Vogel 
3421*1a4e3449SJack F Vogel /**
3422*1a4e3449SJack F Vogel  *  ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
3423*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
3424*1a4e3449SJack F Vogel  *  @enable: enable or disable switch for anti-spoofing
3425*1a4e3449SJack F Vogel  *  @pf: Physical Function pool - do not enable anti-spoofing for the PF
3426*1a4e3449SJack F Vogel  *
3427*1a4e3449SJack F Vogel  **/
3428*1a4e3449SJack F Vogel void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf)
3429*1a4e3449SJack F Vogel {
3430*1a4e3449SJack F Vogel 	int j;
3431*1a4e3449SJack F Vogel 	int pf_target_reg = pf >> 3;
3432*1a4e3449SJack F Vogel 	int pf_target_shift = pf % 8;
3433*1a4e3449SJack F Vogel 	u32 pfvfspoof = 0;
3434*1a4e3449SJack F Vogel 
3435*1a4e3449SJack F Vogel 	if (hw->mac.type == ixgbe_mac_82598EB)
3436*1a4e3449SJack F Vogel 		return;
3437*1a4e3449SJack F Vogel 
3438*1a4e3449SJack F Vogel 	if (enable)
3439*1a4e3449SJack F Vogel 		pfvfspoof = IXGBE_SPOOF_MACAS_MASK;
3440*1a4e3449SJack F Vogel 
3441*1a4e3449SJack F Vogel 	/*
3442*1a4e3449SJack F Vogel 	 * PFVFSPOOF register array is size 8 with 8 bits assigned to
3443*1a4e3449SJack F Vogel 	 * MAC anti-spoof enables in each register array element.
3444*1a4e3449SJack F Vogel 	 */
3445*1a4e3449SJack F Vogel 	for (j = 0; j < IXGBE_PFVFSPOOF_REG_COUNT; j++)
3446*1a4e3449SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof);
3447*1a4e3449SJack F Vogel 
3448*1a4e3449SJack F Vogel 	/* If not enabling anti-spoofing then done */
3449*1a4e3449SJack F Vogel 	if (!enable)
3450*1a4e3449SJack F Vogel 		return;
3451*1a4e3449SJack F Vogel 
3452*1a4e3449SJack F Vogel 	/*
3453*1a4e3449SJack F Vogel 	 * The PF should be allowed to spoof so that it can support
3454*1a4e3449SJack F Vogel 	 * emulation mode NICs.  Reset the bit assigned to the PF
3455*1a4e3449SJack F Vogel 	 */
3456*1a4e3449SJack F Vogel 	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(pf_target_reg));
3457*1a4e3449SJack F Vogel 	pfvfspoof ^= (1 << pf_target_shift);
3458*1a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(pf_target_reg), pfvfspoof);
3459*1a4e3449SJack F Vogel }
3460*1a4e3449SJack F Vogel 
3461*1a4e3449SJack F Vogel /**
3462*1a4e3449SJack F Vogel  *  ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing
3463*1a4e3449SJack F Vogel  *  @hw: pointer to hardware structure
3464*1a4e3449SJack F Vogel  *  @enable: enable or disable switch for VLAN anti-spoofing
3465*1a4e3449SJack F Vogel  *  @pf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
3466*1a4e3449SJack F Vogel  *
3467*1a4e3449SJack F Vogel  **/
3468*1a4e3449SJack F Vogel void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
3469*1a4e3449SJack F Vogel {
3470*1a4e3449SJack F Vogel 	int vf_target_reg = vf >> 3;
3471*1a4e3449SJack F Vogel 	int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT;
3472*1a4e3449SJack F Vogel 	u32 pfvfspoof;
3473*1a4e3449SJack F Vogel 
3474*1a4e3449SJack F Vogel 	if (hw->mac.type == ixgbe_mac_82598EB)
3475*1a4e3449SJack F Vogel 		return;
3476*1a4e3449SJack F Vogel 
3477*1a4e3449SJack F Vogel 	pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
3478*1a4e3449SJack F Vogel 	if (enable)
3479*1a4e3449SJack F Vogel 		pfvfspoof |= (1 << vf_target_shift);
3480*1a4e3449SJack F Vogel 	else
3481*1a4e3449SJack F Vogel 		pfvfspoof &= ~(1 << vf_target_shift);
3482*1a4e3449SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
3483*1a4e3449SJack F Vogel }
3484