xref: /freebsd/sys/dev/ixgbe/ixgbe_common.c (revision c00148556a4cbd3d8fd249c1d32968d95dcdfe29)
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"
3613705f88SJack F Vogel #include "ixgbe_api.h"
3713705f88SJack F Vogel 
3813705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
3913705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
4013705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
4113705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw);
4213705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw);
4313705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
4413705f88SJack F Vogel                                         u16 count);
4513705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count);
4613705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
4713705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
4813705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
4913705f88SJack F Vogel 
5013705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
512969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
522969bf0eSJack F Vogel                                         u16 *san_mac_offset);
532969bf0eSJack F Vogel s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan);
5413705f88SJack F Vogel 
5513705f88SJack F Vogel /**
569ca4041bSJack F Vogel  *  ixgbe_init_ops_generic - Inits function ptrs
579ca4041bSJack F Vogel  *  @hw: pointer to the hardware structure
5813705f88SJack F Vogel  *
599ca4041bSJack F Vogel  *  Initialize the function pointers.
6013705f88SJack F Vogel  **/
619ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
6213705f88SJack F Vogel {
639ca4041bSJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
649ca4041bSJack F Vogel 	struct ixgbe_mac_info *mac = &hw->mac;
659ca4041bSJack F Vogel 	u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
6613705f88SJack F Vogel 
672969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_ops_generic");
682969bf0eSJack F Vogel 
6913705f88SJack F Vogel 	/* EEPROM */
709ca4041bSJack F Vogel 	eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic;
719ca4041bSJack F Vogel 	/* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
729ca4041bSJack F Vogel 	if (eec & (1 << 8))
732969bf0eSJack F Vogel 		eeprom->ops.read = &ixgbe_read_eerd_generic;
749ca4041bSJack F Vogel 	else
759ca4041bSJack F Vogel 		eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic;
769ca4041bSJack F Vogel 	eeprom->ops.write = &ixgbe_write_eeprom_generic;
779ca4041bSJack F Vogel 	eeprom->ops.validate_checksum =
7813705f88SJack F Vogel 	                              &ixgbe_validate_eeprom_checksum_generic;
799ca4041bSJack F Vogel 	eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic;
802969bf0eSJack F Vogel 	eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_generic;
819ca4041bSJack F Vogel 
829ca4041bSJack F Vogel 	/* MAC */
839ca4041bSJack F Vogel 	mac->ops.init_hw = &ixgbe_init_hw_generic;
849ca4041bSJack F Vogel 	mac->ops.reset_hw = NULL;
859ca4041bSJack F Vogel 	mac->ops.start_hw = &ixgbe_start_hw_generic;
869ca4041bSJack F Vogel 	mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic;
879ca4041bSJack F Vogel 	mac->ops.get_media_type = NULL;
881b6e0dbaSJack F Vogel 	mac->ops.get_supported_physical_layer = NULL;
890ac6dfecSJack F Vogel 	mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic;
909ca4041bSJack F Vogel 	mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic;
919ca4041bSJack F Vogel 	mac->ops.stop_adapter = &ixgbe_stop_adapter_generic;
929ca4041bSJack F Vogel 	mac->ops.get_bus_info = &ixgbe_get_bus_info_generic;
931b6e0dbaSJack F Vogel 	mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie;
94d8602bb9SJack F Vogel 	mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync;
95d8602bb9SJack F Vogel 	mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync;
969ca4041bSJack F Vogel 
979ca4041bSJack F Vogel 	/* LEDs */
989ca4041bSJack F Vogel 	mac->ops.led_on = &ixgbe_led_on_generic;
999ca4041bSJack F Vogel 	mac->ops.led_off = &ixgbe_led_off_generic;
1000ac6dfecSJack F Vogel 	mac->ops.blink_led_start = &ixgbe_blink_led_start_generic;
1010ac6dfecSJack F Vogel 	mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic;
1029ca4041bSJack F Vogel 
10313705f88SJack F Vogel 	/* RAR, Multicast, VLAN */
1049ca4041bSJack F Vogel 	mac->ops.set_rar = &ixgbe_set_rar_generic;
1055b7f4cedSJack F Vogel 	mac->ops.clear_rar = &ixgbe_clear_rar_generic;
1060ac6dfecSJack F Vogel 	mac->ops.insert_mac_addr = NULL;
1079ca4041bSJack F Vogel 	mac->ops.set_vmdq = NULL;
1085b7f4cedSJack F Vogel 	mac->ops.clear_vmdq = NULL;
1099ca4041bSJack F Vogel 	mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic;
1109ca4041bSJack F Vogel 	mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic;
1119ca4041bSJack F Vogel 	mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic;
1129ca4041bSJack F Vogel 	mac->ops.enable_mc = &ixgbe_enable_mc_generic;
1139ca4041bSJack F Vogel 	mac->ops.disable_mc = &ixgbe_disable_mc_generic;
1145b7f4cedSJack F Vogel 	mac->ops.clear_vfta = NULL;
1155b7f4cedSJack F Vogel 	mac->ops.set_vfta = NULL;
1165b7f4cedSJack F Vogel 	mac->ops.init_uta_tables = NULL;
1179ca4041bSJack F Vogel 
1180ac6dfecSJack F Vogel 	/* Flow Control */
1190ac6dfecSJack F Vogel 	mac->ops.fc_enable = &ixgbe_fc_enable_generic;
1209ca4041bSJack F Vogel 
1219ca4041bSJack F Vogel 	/* Link */
1229ca4041bSJack F Vogel 	mac->ops.get_link_capabilities = NULL;
1239ca4041bSJack F Vogel 	mac->ops.setup_link = NULL;
1249ca4041bSJack F Vogel 	mac->ops.check_link = NULL;
12513705f88SJack F Vogel 
12613705f88SJack F Vogel 	return IXGBE_SUCCESS;
12713705f88SJack F Vogel }
12813705f88SJack F Vogel 
12913705f88SJack F Vogel /**
1309ca4041bSJack F Vogel  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
13113705f88SJack F Vogel  *  @hw: pointer to hardware structure
13213705f88SJack F Vogel  *
13313705f88SJack F Vogel  *  Starts the hardware by filling the bus info structure and media type, clears
13413705f88SJack F Vogel  *  all on chip counters, initializes receive address registers, multicast
13513705f88SJack F Vogel  *  table, VLAN filter table, calls routine to set up link and flow control
13613705f88SJack F Vogel  *  settings, and leaves transmit and receive units disabled and uninitialized
13713705f88SJack F Vogel  **/
13813705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
13913705f88SJack F Vogel {
14013705f88SJack F Vogel 	u32 ctrl_ext;
1410ac6dfecSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
14213705f88SJack F Vogel 
1432969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_start_hw_generic");
1442969bf0eSJack F Vogel 
14513705f88SJack F Vogel 	/* Set the media type */
1469ca4041bSJack F Vogel 	hw->phy.media_type = hw->mac.ops.get_media_type(hw);
14713705f88SJack F Vogel 
1480ac6dfecSJack F Vogel 	/* PHY ops initialization must be done in reset_hw() */
14913705f88SJack F Vogel 
15013705f88SJack F Vogel 	/* Clear the VLAN filter table */
1519ca4041bSJack F Vogel 	hw->mac.ops.clear_vfta(hw);
15213705f88SJack F Vogel 
15313705f88SJack F Vogel 	/* Clear statistics registers */
1549ca4041bSJack F Vogel 	hw->mac.ops.clear_hw_cntrs(hw);
15513705f88SJack F Vogel 
15613705f88SJack F Vogel 	/* Set No Snoop Disable */
15713705f88SJack F Vogel 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
15813705f88SJack F Vogel 	ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
15913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
1609ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
16113705f88SJack F Vogel 
1620ac6dfecSJack F Vogel 	/* Setup flow control */
1630ac6dfecSJack F Vogel 	ixgbe_setup_fc(hw, 0);
1640ac6dfecSJack F Vogel 
16513705f88SJack F Vogel 	/* Clear adapter stopped flag */
16613705f88SJack F Vogel 	hw->adapter_stopped = FALSE;
16713705f88SJack F Vogel 
1680ac6dfecSJack F Vogel 	return ret_val;
16913705f88SJack F Vogel }
17013705f88SJack F Vogel 
17113705f88SJack F Vogel /**
17213705f88SJack F Vogel  *  ixgbe_init_hw_generic - Generic hardware initialization
17313705f88SJack F Vogel  *  @hw: pointer to hardware structure
17413705f88SJack F Vogel  *
1759ca4041bSJack F Vogel  *  Initialize the hardware by resetting the hardware, filling the bus info
17613705f88SJack F Vogel  *  structure and media type, clears all on chip counters, initializes receive
17713705f88SJack F Vogel  *  address registers, multicast table, VLAN filter table, calls routine to set
17813705f88SJack F Vogel  *  up link and flow control settings, and leaves transmit and receive units
17913705f88SJack F Vogel  *  disabled and uninitialized
18013705f88SJack F Vogel  **/
18113705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
18213705f88SJack F Vogel {
1830ac6dfecSJack F Vogel 	s32 status = IXGBE_SUCCESS;
1840ac6dfecSJack F Vogel 
1852969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_hw_generic");
1862969bf0eSJack F Vogel 
18713705f88SJack F Vogel 	/* Reset the hardware */
1880ac6dfecSJack F Vogel 	status = hw->mac.ops.reset_hw(hw);
18913705f88SJack F Vogel 
1900ac6dfecSJack F Vogel 	if (status == IXGBE_SUCCESS) {
19113705f88SJack F Vogel 		/* Start the HW */
1920ac6dfecSJack F Vogel 		status = hw->mac.ops.start_hw(hw);
1930ac6dfecSJack F Vogel 	}
19413705f88SJack F Vogel 
1950ac6dfecSJack F Vogel 	return status;
19613705f88SJack F Vogel }
19713705f88SJack F Vogel 
19813705f88SJack F Vogel /**
19913705f88SJack F Vogel  *  ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
20013705f88SJack F Vogel  *  @hw: pointer to hardware structure
20113705f88SJack F Vogel  *
20213705f88SJack F Vogel  *  Clears all hardware statistics counters by reading them from the hardware
20313705f88SJack F Vogel  *  Statistics counters are clear on read.
20413705f88SJack F Vogel  **/
20513705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
20613705f88SJack F Vogel {
20713705f88SJack F Vogel 	u16 i = 0;
20813705f88SJack F Vogel 
2092969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_clear_hw_cntrs_generic");
2102969bf0eSJack F Vogel 
21113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_CRCERRS);
21213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ILLERRC);
21313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ERRBC);
21413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MSPDC);
21513705f88SJack F Vogel 	for (i = 0; i < 8; i++)
21613705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_MPC(i));
21713705f88SJack F Vogel 
21813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MLFC);
21913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MRFC);
22013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RLEC);
22113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXONTXC);
22213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
2230ac6dfecSJack F Vogel 	if (hw->mac.type >= ixgbe_mac_82599EB) {
2240ac6dfecSJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
2250ac6dfecSJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
2260ac6dfecSJack F Vogel 	} else {
2271b6e0dbaSJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_LXONRXC);
22813705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
2290ac6dfecSJack F Vogel 	}
23013705f88SJack F Vogel 
23113705f88SJack F Vogel 	for (i = 0; i < 8; i++) {
23213705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
23313705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
2340ac6dfecSJack F Vogel 		if (hw->mac.type >= ixgbe_mac_82599EB) {
2350ac6dfecSJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
2360ac6dfecSJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
2370ac6dfecSJack F Vogel 		} else {
2381b6e0dbaSJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
23913705f88SJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
24013705f88SJack F Vogel 		}
2410ac6dfecSJack F Vogel 	}
2420ac6dfecSJack F Vogel 	if (hw->mac.type >= ixgbe_mac_82599EB)
2430ac6dfecSJack F Vogel 		for (i = 0; i < 8; i++)
2440ac6dfecSJack F Vogel 			IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
24513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC64);
24613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC127);
24713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC255);
24813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC511);
24913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC1023);
25013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC1522);
25113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GPRC);
25213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_BPRC);
25313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MPRC);
25413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GPTC);
25513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GORCL);
25613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GORCH);
25713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GOTCL);
25813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GOTCH);
25913705f88SJack F Vogel 	for (i = 0; i < 8; i++)
26013705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_RNBC(i));
26113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RUC);
26213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RFC);
26313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ROC);
26413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RJC);
26513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPRC);
26613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPDC);
26713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPTC);
26813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TORL);
26913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TORH);
27013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TPR);
27113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TPT);
27213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC64);
27313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC127);
27413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC255);
27513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC511);
27613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC1023);
27713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC1522);
27813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MPTC);
27913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_BPTC);
28013705f88SJack F Vogel 	for (i = 0; i < 16; i++) {
28113705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QPRC(i));
28213705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QBRC(i));
28313705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QPTC(i));
28413705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QBTC(i));
28513705f88SJack F Vogel 	}
28613705f88SJack F Vogel 
28713705f88SJack F Vogel 	return IXGBE_SUCCESS;
28813705f88SJack F Vogel }
28913705f88SJack F Vogel 
29013705f88SJack F Vogel /**
2911b6e0dbaSJack F Vogel  *  ixgbe_read_pba_num_generic - Reads part number from EEPROM
2929ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
2939ca4041bSJack F Vogel  *  @pba_num: stores the part number from the EEPROM
2949ca4041bSJack F Vogel  *
2959ca4041bSJack F Vogel  *  Reads the part number from the EEPROM.
2969ca4041bSJack F Vogel  **/
2979ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num)
2989ca4041bSJack F Vogel {
2999ca4041bSJack F Vogel 	s32 ret_val;
3009ca4041bSJack F Vogel 	u16 data;
3019ca4041bSJack F Vogel 
3029ca4041bSJack F Vogel 	DEBUGFUNC("ixgbe_read_pba_num_generic");
3039ca4041bSJack F Vogel 
3049ca4041bSJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
3059ca4041bSJack F Vogel 	if (ret_val) {
3069ca4041bSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
3079ca4041bSJack F Vogel 		return ret_val;
3089ca4041bSJack F Vogel 	}
3099ca4041bSJack F Vogel 	*pba_num = (u32)(data << 16);
3109ca4041bSJack F Vogel 
3119ca4041bSJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data);
3129ca4041bSJack F Vogel 	if (ret_val) {
3139ca4041bSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
3149ca4041bSJack F Vogel 		return ret_val;
3159ca4041bSJack F Vogel 	}
3169ca4041bSJack F Vogel 	*pba_num |= data;
3179ca4041bSJack F Vogel 
3189ca4041bSJack F Vogel 	return IXGBE_SUCCESS;
3199ca4041bSJack F Vogel }
3209ca4041bSJack F Vogel 
3219ca4041bSJack F Vogel /**
32213705f88SJack F Vogel  *  ixgbe_get_mac_addr_generic - Generic get MAC address
32313705f88SJack F Vogel  *  @hw: pointer to hardware structure
32413705f88SJack F Vogel  *  @mac_addr: Adapter MAC address
32513705f88SJack F Vogel  *
32613705f88SJack F Vogel  *  Reads the adapter's MAC address from first Receive Address Register (RAR0)
32713705f88SJack F Vogel  *  A reset of the adapter must be performed prior to calling this function
32813705f88SJack F Vogel  *  in order for the MAC address to have been loaded from the EEPROM into RAR0
32913705f88SJack F Vogel  **/
33013705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
33113705f88SJack F Vogel {
33213705f88SJack F Vogel 	u32 rar_high;
33313705f88SJack F Vogel 	u32 rar_low;
33413705f88SJack F Vogel 	u16 i;
33513705f88SJack F Vogel 
3362969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_mac_addr_generic");
3372969bf0eSJack F Vogel 
33813705f88SJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0));
33913705f88SJack F Vogel 	rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0));
34013705f88SJack F Vogel 
34113705f88SJack F Vogel 	for (i = 0; i < 4; i++)
34213705f88SJack F Vogel 		mac_addr[i] = (u8)(rar_low >> (i*8));
34313705f88SJack F Vogel 
34413705f88SJack F Vogel 	for (i = 0; i < 2; i++)
34513705f88SJack F Vogel 		mac_addr[i+4] = (u8)(rar_high >> (i*8));
34613705f88SJack F Vogel 
34713705f88SJack F Vogel 	return IXGBE_SUCCESS;
34813705f88SJack F Vogel }
34913705f88SJack F Vogel 
35013705f88SJack F Vogel /**
35113705f88SJack F Vogel  *  ixgbe_get_bus_info_generic - Generic set PCI bus info
35213705f88SJack F Vogel  *  @hw: pointer to hardware structure
35313705f88SJack F Vogel  *
35413705f88SJack F Vogel  *  Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure
35513705f88SJack F Vogel  **/
35613705f88SJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
35713705f88SJack F Vogel {
3581b6e0dbaSJack F Vogel 	struct ixgbe_mac_info *mac = &hw->mac;
35913705f88SJack F Vogel 	u16 link_status;
36013705f88SJack F Vogel 
3612969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_bus_info_generic");
3622969bf0eSJack F Vogel 
36313705f88SJack F Vogel 	hw->bus.type = ixgbe_bus_type_pci_express;
36413705f88SJack F Vogel 
36513705f88SJack F Vogel 	/* Get the negotiated link width and speed from PCI config space */
36613705f88SJack F Vogel 	link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS);
36713705f88SJack F Vogel 
36813705f88SJack F Vogel 	switch (link_status & IXGBE_PCI_LINK_WIDTH) {
36913705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_1:
37013705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x1;
37113705f88SJack F Vogel 		break;
37213705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_2:
37313705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x2;
37413705f88SJack F Vogel 		break;
37513705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_4:
37613705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x4;
37713705f88SJack F Vogel 		break;
37813705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_8:
37913705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x8;
38013705f88SJack F Vogel 		break;
38113705f88SJack F Vogel 	default:
38213705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_unknown;
38313705f88SJack F Vogel 		break;
38413705f88SJack F Vogel 	}
38513705f88SJack F Vogel 
38613705f88SJack F Vogel 	switch (link_status & IXGBE_PCI_LINK_SPEED) {
38713705f88SJack F Vogel 	case IXGBE_PCI_LINK_SPEED_2500:
38813705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_2500;
38913705f88SJack F Vogel 		break;
39013705f88SJack F Vogel 	case IXGBE_PCI_LINK_SPEED_5000:
39113705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_5000;
39213705f88SJack F Vogel 		break;
39313705f88SJack F Vogel 	default:
39413705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_unknown;
39513705f88SJack F Vogel 		break;
39613705f88SJack F Vogel 	}
39713705f88SJack F Vogel 
3981b6e0dbaSJack F Vogel 	mac->ops.set_lan_id(hw);
3991b6e0dbaSJack F Vogel 
40013705f88SJack F Vogel 	return IXGBE_SUCCESS;
40113705f88SJack F Vogel }
40213705f88SJack F Vogel 
40313705f88SJack F Vogel /**
4041b6e0dbaSJack F Vogel  *  ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
4051b6e0dbaSJack F Vogel  *  @hw: pointer to the HW structure
4061b6e0dbaSJack F Vogel  *
4071b6e0dbaSJack F Vogel  *  Determines the LAN function id by reading memory-mapped registers
4081b6e0dbaSJack F Vogel  *  and swaps the port value if requested.
4091b6e0dbaSJack F Vogel  **/
4101b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
4111b6e0dbaSJack F Vogel {
4121b6e0dbaSJack F Vogel 	struct ixgbe_bus_info *bus = &hw->bus;
4131b6e0dbaSJack F Vogel 	u32 reg;
4141b6e0dbaSJack F Vogel 
4152969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
4162969bf0eSJack F Vogel 
4171b6e0dbaSJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_STATUS);
4181b6e0dbaSJack F Vogel 	bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT;
4190ac6dfecSJack F Vogel 	bus->lan_id = bus->func;
4201b6e0dbaSJack F Vogel 
4211b6e0dbaSJack F Vogel 	/* check for a port swap */
4221b6e0dbaSJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_FACTPS);
4231b6e0dbaSJack F Vogel 	if (reg & IXGBE_FACTPS_LFS)
4241b6e0dbaSJack F Vogel 		bus->func ^= 0x1;
4251b6e0dbaSJack F Vogel }
4261b6e0dbaSJack F Vogel 
4271b6e0dbaSJack F Vogel /**
4289ca4041bSJack F Vogel  *  ixgbe_stop_adapter_generic - Generic stop Tx/Rx units
42913705f88SJack F Vogel  *  @hw: pointer to hardware structure
43013705f88SJack F Vogel  *
43113705f88SJack F Vogel  *  Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
43213705f88SJack F Vogel  *  disables transmit and receive units. The adapter_stopped flag is used by
43313705f88SJack F Vogel  *  the shared code and drivers to determine if the adapter is in a stopped
43413705f88SJack F Vogel  *  state and should not touch the hardware.
43513705f88SJack F Vogel  **/
43613705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
43713705f88SJack F Vogel {
43813705f88SJack F Vogel 	u32 number_of_queues;
43913705f88SJack F Vogel 	u32 reg_val;
44013705f88SJack F Vogel 	u16 i;
44113705f88SJack F Vogel 
4422969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_stop_adapter_generic");
4432969bf0eSJack F Vogel 
44413705f88SJack F Vogel 	/*
44513705f88SJack F Vogel 	 * Set the adapter_stopped flag so other driver functions stop touching
44613705f88SJack F Vogel 	 * the hardware
44713705f88SJack F Vogel 	 */
44813705f88SJack F Vogel 	hw->adapter_stopped = TRUE;
44913705f88SJack F Vogel 
45013705f88SJack F Vogel 	/* Disable the receive unit */
45113705f88SJack F Vogel 	reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
45213705f88SJack F Vogel 	reg_val &= ~(IXGBE_RXCTRL_RXEN);
45313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val);
4549ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
45513705f88SJack F Vogel 	msec_delay(2);
45613705f88SJack F Vogel 
45713705f88SJack F Vogel 	/* Clear interrupt mask to stop from interrupts being generated */
45813705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
45913705f88SJack F Vogel 
46013705f88SJack F Vogel 	/* Clear any pending interrupts */
46113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_EICR);
46213705f88SJack F Vogel 
46313705f88SJack F Vogel 	/* Disable the transmit unit.  Each queue must be disabled. */
4649ca4041bSJack F Vogel 	number_of_queues = hw->mac.max_tx_queues;
46513705f88SJack F Vogel 	for (i = 0; i < number_of_queues; i++) {
46613705f88SJack F Vogel 		reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
46713705f88SJack F Vogel 		if (reg_val & IXGBE_TXDCTL_ENABLE) {
46813705f88SJack F Vogel 			reg_val &= ~IXGBE_TXDCTL_ENABLE;
46913705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val);
47013705f88SJack F Vogel 		}
47113705f88SJack F Vogel 	}
47213705f88SJack F Vogel 
4739ca4041bSJack F Vogel 	/*
4749ca4041bSJack F Vogel 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
4759ca4041bSJack F Vogel 	 * access and verify no pending requests
4769ca4041bSJack F Vogel 	 */
477c0014855SJack F Vogel 	ixgbe_disable_pcie_master(hw);
4789ca4041bSJack F Vogel 
47913705f88SJack F Vogel 	return IXGBE_SUCCESS;
48013705f88SJack F Vogel }
48113705f88SJack F Vogel 
48213705f88SJack F Vogel /**
48313705f88SJack F Vogel  *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
48413705f88SJack F Vogel  *  @hw: pointer to hardware structure
48513705f88SJack F Vogel  *  @index: led number to turn on
48613705f88SJack F Vogel  **/
48713705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
48813705f88SJack F Vogel {
48913705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
49013705f88SJack F Vogel 
4912969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_led_on_generic");
4922969bf0eSJack F Vogel 
49313705f88SJack F Vogel 	/* To turn on the LED, set mode to ON. */
49413705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
49513705f88SJack F Vogel 	led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index);
49613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
4979ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
49813705f88SJack F Vogel 
49913705f88SJack F Vogel 	return IXGBE_SUCCESS;
50013705f88SJack F Vogel }
50113705f88SJack F Vogel 
50213705f88SJack F Vogel /**
50313705f88SJack F Vogel  *  ixgbe_led_off_generic - Turns off the software controllable LEDs.
50413705f88SJack F Vogel  *  @hw: pointer to hardware structure
50513705f88SJack F Vogel  *  @index: led number to turn off
50613705f88SJack F Vogel  **/
50713705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
50813705f88SJack F Vogel {
50913705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
51013705f88SJack F Vogel 
5112969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_led_off_generic");
5122969bf0eSJack F Vogel 
51313705f88SJack F Vogel 	/* To turn off the LED, set mode to OFF. */
51413705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
51513705f88SJack F Vogel 	led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index);
51613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
5179ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
51813705f88SJack F Vogel 
51913705f88SJack F Vogel 	return IXGBE_SUCCESS;
52013705f88SJack F Vogel }
52113705f88SJack F Vogel 
52213705f88SJack F Vogel /**
52313705f88SJack F Vogel  *  ixgbe_init_eeprom_params_generic - Initialize EEPROM params
52413705f88SJack F Vogel  *  @hw: pointer to hardware structure
52513705f88SJack F Vogel  *
52613705f88SJack F Vogel  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
52713705f88SJack F Vogel  *  ixgbe_hw struct in order to set up EEPROM access.
52813705f88SJack F Vogel  **/
52913705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
53013705f88SJack F Vogel {
53113705f88SJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
53213705f88SJack F Vogel 	u32 eec;
53313705f88SJack F Vogel 	u16 eeprom_size;
53413705f88SJack F Vogel 
5352969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_eeprom_params_generic");
5362969bf0eSJack F Vogel 
53713705f88SJack F Vogel 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
53813705f88SJack F Vogel 		eeprom->type = ixgbe_eeprom_none;
5395b7f4cedSJack F Vogel 		/* Set default semaphore delay to 10ms which is a well
5405b7f4cedSJack F Vogel 		 * tested value */
5415b7f4cedSJack F Vogel 		eeprom->semaphore_delay = 10;
54213705f88SJack F Vogel 
54313705f88SJack F Vogel 		/*
54413705f88SJack F Vogel 		 * Check for EEPROM present first.
54513705f88SJack F Vogel 		 * If not present leave as none
54613705f88SJack F Vogel 		 */
54713705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
54813705f88SJack F Vogel 		if (eec & IXGBE_EEC_PRES) {
54913705f88SJack F Vogel 			eeprom->type = ixgbe_eeprom_spi;
55013705f88SJack F Vogel 
55113705f88SJack F Vogel 			/*
55213705f88SJack F Vogel 			 * SPI EEPROM is assumed here.  This code would need to
55313705f88SJack F Vogel 			 * change if a future EEPROM is not SPI.
55413705f88SJack F Vogel 			 */
55513705f88SJack F Vogel 			eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
55613705f88SJack F Vogel 			                    IXGBE_EEC_SIZE_SHIFT);
55713705f88SJack F Vogel 			eeprom->word_size = 1 << (eeprom_size +
5582969bf0eSJack F Vogel 			                     IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT);
55913705f88SJack F Vogel 		}
56013705f88SJack F Vogel 
56113705f88SJack F Vogel 		if (eec & IXGBE_EEC_ADDR_SIZE)
56213705f88SJack F Vogel 			eeprom->address_bits = 16;
56313705f88SJack F Vogel 		else
56413705f88SJack F Vogel 			eeprom->address_bits = 8;
56513705f88SJack F Vogel 		DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: "
56613705f88SJack F Vogel 		          "%d\n", eeprom->type, eeprom->word_size,
56713705f88SJack F Vogel 		          eeprom->address_bits);
56813705f88SJack F Vogel 	}
56913705f88SJack F Vogel 
57013705f88SJack F Vogel 	return IXGBE_SUCCESS;
57113705f88SJack F Vogel }
57213705f88SJack F Vogel 
57313705f88SJack F Vogel /**
57413705f88SJack F Vogel  *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
57513705f88SJack F Vogel  *  @hw: pointer to hardware structure
57613705f88SJack F Vogel  *  @offset: offset within the EEPROM to be written to
57713705f88SJack F Vogel  *  @data: 16 bit word to be written to the EEPROM
57813705f88SJack F Vogel  *
57913705f88SJack F Vogel  *  If ixgbe_eeprom_update_checksum is not called after this function, the
58013705f88SJack F Vogel  *  EEPROM will most likely contain an invalid checksum.
58113705f88SJack F Vogel  **/
58213705f88SJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
58313705f88SJack F Vogel {
58413705f88SJack F Vogel 	s32 status;
58513705f88SJack F Vogel 	u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
58613705f88SJack F Vogel 
5872969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_write_eeprom_generic");
5882969bf0eSJack F Vogel 
5899ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
5909ca4041bSJack F Vogel 
5919ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
5929ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
5939ca4041bSJack F Vogel 		goto out;
5949ca4041bSJack F Vogel 	}
5959ca4041bSJack F Vogel 
59613705f88SJack F Vogel 	/* Prepare the EEPROM for writing  */
59713705f88SJack F Vogel 	status = ixgbe_acquire_eeprom(hw);
59813705f88SJack F Vogel 
59913705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
60013705f88SJack F Vogel 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
60113705f88SJack F Vogel 			ixgbe_release_eeprom(hw);
60213705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
60313705f88SJack F Vogel 		}
60413705f88SJack F Vogel 	}
60513705f88SJack F Vogel 
60613705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
60713705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
60813705f88SJack F Vogel 
60913705f88SJack F Vogel 		/*  Send the WRITE ENABLE command (8 bit opcode )  */
61013705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI,
61113705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
61213705f88SJack F Vogel 
61313705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
61413705f88SJack F Vogel 
61513705f88SJack F Vogel 		/*
61613705f88SJack F Vogel 		 * Some SPI eeproms use the 8th address bit embedded in the
61713705f88SJack F Vogel 		 * opcode
61813705f88SJack F Vogel 		 */
61913705f88SJack F Vogel 		if ((hw->eeprom.address_bits == 8) && (offset >= 128))
62013705f88SJack F Vogel 			write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
62113705f88SJack F Vogel 
62213705f88SJack F Vogel 		/* Send the Write command (8-bit opcode + addr) */
62313705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, write_opcode,
62413705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
62513705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
62613705f88SJack F Vogel 		                            hw->eeprom.address_bits);
62713705f88SJack F Vogel 
62813705f88SJack F Vogel 		/* Send the data */
62913705f88SJack F Vogel 		data = (data >> 8) | (data << 8);
63013705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, data, 16);
63113705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
63213705f88SJack F Vogel 
63313705f88SJack F Vogel 		/* Done with writing - release the EEPROM */
63413705f88SJack F Vogel 		ixgbe_release_eeprom(hw);
63513705f88SJack F Vogel 	}
63613705f88SJack F Vogel 
6379ca4041bSJack F Vogel out:
63813705f88SJack F Vogel 	return status;
63913705f88SJack F Vogel }
64013705f88SJack F Vogel 
64113705f88SJack F Vogel /**
64213705f88SJack F Vogel  *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
64313705f88SJack F Vogel  *  @hw: pointer to hardware structure
64413705f88SJack F Vogel  *  @offset: offset within the EEPROM to be read
64513705f88SJack F Vogel  *  @data: read 16 bit value from EEPROM
64613705f88SJack F Vogel  *
64713705f88SJack F Vogel  *  Reads 16 bit value from EEPROM through bit-bang method
64813705f88SJack F Vogel  **/
64913705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
65013705f88SJack F Vogel                                        u16 *data)
65113705f88SJack F Vogel {
65213705f88SJack F Vogel 	s32 status;
65313705f88SJack F Vogel 	u16 word_in;
65413705f88SJack F Vogel 	u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
65513705f88SJack F Vogel 
6562969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic");
6572969bf0eSJack F Vogel 
6589ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
6599ca4041bSJack F Vogel 
6609ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
6619ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
6629ca4041bSJack F Vogel 		goto out;
6639ca4041bSJack F Vogel 	}
6649ca4041bSJack F Vogel 
66513705f88SJack F Vogel 	/* Prepare the EEPROM for reading  */
66613705f88SJack F Vogel 	status = ixgbe_acquire_eeprom(hw);
66713705f88SJack F Vogel 
66813705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
66913705f88SJack F Vogel 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
67013705f88SJack F Vogel 			ixgbe_release_eeprom(hw);
67113705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
67213705f88SJack F Vogel 		}
67313705f88SJack F Vogel 	}
67413705f88SJack F Vogel 
67513705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
67613705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
67713705f88SJack F Vogel 
67813705f88SJack F Vogel 		/*
67913705f88SJack F Vogel 		 * Some SPI eeproms use the 8th address bit embedded in the
68013705f88SJack F Vogel 		 * opcode
68113705f88SJack F Vogel 		 */
68213705f88SJack F Vogel 		if ((hw->eeprom.address_bits == 8) && (offset >= 128))
68313705f88SJack F Vogel 			read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
68413705f88SJack F Vogel 
68513705f88SJack F Vogel 		/* Send the READ command (opcode + addr) */
68613705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, read_opcode,
68713705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
68813705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
68913705f88SJack F Vogel 		                            hw->eeprom.address_bits);
69013705f88SJack F Vogel 
69113705f88SJack F Vogel 		/* Read the data. */
69213705f88SJack F Vogel 		word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
69313705f88SJack F Vogel 		*data = (word_in >> 8) | (word_in << 8);
69413705f88SJack F Vogel 
69513705f88SJack F Vogel 		/* End this read operation */
69613705f88SJack F Vogel 		ixgbe_release_eeprom(hw);
69713705f88SJack F Vogel 	}
69813705f88SJack F Vogel 
6999ca4041bSJack F Vogel out:
70013705f88SJack F Vogel 	return status;
70113705f88SJack F Vogel }
70213705f88SJack F Vogel 
70313705f88SJack F Vogel /**
7042969bf0eSJack F Vogel  *  ixgbe_read_eerd_generic - Read EEPROM word using EERD
70513705f88SJack F Vogel  *  @hw: pointer to hardware structure
70613705f88SJack F Vogel  *  @offset: offset of  word in the EEPROM to read
70713705f88SJack F Vogel  *  @data: word read from the EEPROM
70813705f88SJack F Vogel  *
70913705f88SJack F Vogel  *  Reads a 16 bit word from the EEPROM using the EERD register.
71013705f88SJack F Vogel  **/
7112969bf0eSJack F Vogel s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
71213705f88SJack F Vogel {
71313705f88SJack F Vogel 	u32 eerd;
71413705f88SJack F Vogel 	s32 status;
71513705f88SJack F Vogel 
7162969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_read_eerd_generic");
7172969bf0eSJack F Vogel 
7189ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
7199ca4041bSJack F Vogel 
7209ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
7219ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
7229ca4041bSJack F Vogel 		goto out;
7239ca4041bSJack F Vogel 	}
7249ca4041bSJack F Vogel 
7252969bf0eSJack F Vogel 	eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) +
7262969bf0eSJack F Vogel 	       IXGBE_EEPROM_RW_REG_START;
72713705f88SJack F Vogel 
72813705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
7292969bf0eSJack F Vogel 	status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
73013705f88SJack F Vogel 
73113705f88SJack F Vogel 	if (status == IXGBE_SUCCESS)
73213705f88SJack F Vogel 		*data = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
7332969bf0eSJack F Vogel 		         IXGBE_EEPROM_RW_REG_DATA);
73413705f88SJack F Vogel 	else
73513705f88SJack F Vogel 		DEBUGOUT("Eeprom read timed out\n");
73613705f88SJack F Vogel 
7379ca4041bSJack F Vogel out:
73813705f88SJack F Vogel 	return status;
73913705f88SJack F Vogel }
74013705f88SJack F Vogel 
74113705f88SJack F Vogel /**
7422969bf0eSJack F Vogel  *  ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
74313705f88SJack F Vogel  *  @hw: pointer to hardware structure
7442969bf0eSJack F Vogel  *  @ee_reg: EEPROM flag for polling
74513705f88SJack F Vogel  *
7462969bf0eSJack F Vogel  *  Polls the status bit (bit 1) of the EERD or EEWR to determine when the
7472969bf0eSJack F Vogel  *  read or write is done respectively.
74813705f88SJack F Vogel  **/
7492969bf0eSJack F Vogel s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
75013705f88SJack F Vogel {
75113705f88SJack F Vogel 	u32 i;
75213705f88SJack F Vogel 	u32 reg;
75313705f88SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM;
75413705f88SJack F Vogel 
7552969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_poll_eerd_eewr_done");
7562969bf0eSJack F Vogel 
7572969bf0eSJack F Vogel 	for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) {
7582969bf0eSJack F Vogel 		if (ee_reg == IXGBE_NVM_POLL_READ)
75913705f88SJack F Vogel 			reg = IXGBE_READ_REG(hw, IXGBE_EERD);
7602969bf0eSJack F Vogel 		else
7612969bf0eSJack F Vogel 			reg = IXGBE_READ_REG(hw, IXGBE_EEWR);
7622969bf0eSJack F Vogel 
7632969bf0eSJack F Vogel 		if (reg & IXGBE_EEPROM_RW_REG_DONE) {
76413705f88SJack F Vogel 			status = IXGBE_SUCCESS;
76513705f88SJack F Vogel 			break;
76613705f88SJack F Vogel 		}
76713705f88SJack F Vogel 		usec_delay(5);
76813705f88SJack F Vogel 	}
76913705f88SJack F Vogel 	return status;
77013705f88SJack F Vogel }
77113705f88SJack F Vogel 
77213705f88SJack F Vogel /**
77313705f88SJack F Vogel  *  ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang
77413705f88SJack F Vogel  *  @hw: pointer to hardware structure
77513705f88SJack F Vogel  *
77613705f88SJack F Vogel  *  Prepares EEPROM for access using bit-bang method. This function should
77713705f88SJack F Vogel  *  be called before issuing a command to the EEPROM.
77813705f88SJack F Vogel  **/
77913705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
78013705f88SJack F Vogel {
78113705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
78213705f88SJack F Vogel 	u32 eec;
78313705f88SJack F Vogel 	u32 i;
78413705f88SJack F Vogel 
7852969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_acquire_eeprom");
7862969bf0eSJack F Vogel 
78713705f88SJack F Vogel 	if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS)
78813705f88SJack F Vogel 		status = IXGBE_ERR_SWFW_SYNC;
78913705f88SJack F Vogel 
79013705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
79113705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
79213705f88SJack F Vogel 
79313705f88SJack F Vogel 		/* Request EEPROM Access */
79413705f88SJack F Vogel 		eec |= IXGBE_EEC_REQ;
79513705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
79613705f88SJack F Vogel 
79713705f88SJack F Vogel 		for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
79813705f88SJack F Vogel 			eec = IXGBE_READ_REG(hw, IXGBE_EEC);
79913705f88SJack F Vogel 			if (eec & IXGBE_EEC_GNT)
80013705f88SJack F Vogel 				break;
80113705f88SJack F Vogel 			usec_delay(5);
80213705f88SJack F Vogel 		}
80313705f88SJack F Vogel 
8049ca4041bSJack F Vogel 		/* Release if grant not acquired */
80513705f88SJack F Vogel 		if (!(eec & IXGBE_EEC_GNT)) {
80613705f88SJack F Vogel 			eec &= ~IXGBE_EEC_REQ;
80713705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
80813705f88SJack F Vogel 			DEBUGOUT("Could not acquire EEPROM grant\n");
80913705f88SJack F Vogel 
81013705f88SJack F Vogel 			ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
81113705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
81213705f88SJack F Vogel 		}
81313705f88SJack F Vogel 	}
81413705f88SJack F Vogel 
81513705f88SJack F Vogel 	/* Setup EEPROM for Read/Write */
81613705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
81713705f88SJack F Vogel 		/* Clear CS and SK */
81813705f88SJack F Vogel 		eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
81913705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
82013705f88SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
82113705f88SJack F Vogel 		usec_delay(1);
82213705f88SJack F Vogel 	}
82313705f88SJack F Vogel 	return status;
82413705f88SJack F Vogel }
82513705f88SJack F Vogel 
82613705f88SJack F Vogel /**
82713705f88SJack F Vogel  *  ixgbe_get_eeprom_semaphore - Get hardware semaphore
82813705f88SJack F Vogel  *  @hw: pointer to hardware structure
82913705f88SJack F Vogel  *
83013705f88SJack F Vogel  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
83113705f88SJack F Vogel  **/
83213705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
83313705f88SJack F Vogel {
83413705f88SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM;
835d8602bb9SJack F Vogel 	u32 timeout = 2000;
83613705f88SJack F Vogel 	u32 i;
83713705f88SJack F Vogel 	u32 swsm;
83813705f88SJack F Vogel 
8392969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_eeprom_semaphore");
8402969bf0eSJack F Vogel 
84113705f88SJack F Vogel 	/* Get SMBI software semaphore between device drivers first */
84213705f88SJack F Vogel 	for (i = 0; i < timeout; i++) {
84313705f88SJack F Vogel 		/*
84413705f88SJack F Vogel 		 * If the SMBI bit is 0 when we read it, then the bit will be
84513705f88SJack F Vogel 		 * set and we have the semaphore
84613705f88SJack F Vogel 		 */
84713705f88SJack F Vogel 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
84813705f88SJack F Vogel 		if (!(swsm & IXGBE_SWSM_SMBI)) {
84913705f88SJack F Vogel 			status = IXGBE_SUCCESS;
85013705f88SJack F Vogel 			break;
85113705f88SJack F Vogel 		}
8520ac6dfecSJack F Vogel 		usec_delay(50);
85313705f88SJack F Vogel 	}
85413705f88SJack F Vogel 
85513705f88SJack F Vogel 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
85613705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
85713705f88SJack F Vogel 		for (i = 0; i < timeout; i++) {
85813705f88SJack F Vogel 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
85913705f88SJack F Vogel 
86013705f88SJack F Vogel 			/* Set the SW EEPROM semaphore bit to request access */
86113705f88SJack F Vogel 			swsm |= IXGBE_SWSM_SWESMBI;
86213705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
86313705f88SJack F Vogel 
86413705f88SJack F Vogel 			/*
86513705f88SJack F Vogel 			 * If we set the bit successfully then we got the
86613705f88SJack F Vogel 			 * semaphore.
86713705f88SJack F Vogel 			 */
86813705f88SJack F Vogel 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
86913705f88SJack F Vogel 			if (swsm & IXGBE_SWSM_SWESMBI)
87013705f88SJack F Vogel 				break;
87113705f88SJack F Vogel 
87213705f88SJack F Vogel 			usec_delay(50);
87313705f88SJack F Vogel 		}
87413705f88SJack F Vogel 
87513705f88SJack F Vogel 		/*
87613705f88SJack F Vogel 		 * Release semaphores and return error if SW EEPROM semaphore
87713705f88SJack F Vogel 		 * was not granted because we don't have access to the EEPROM
87813705f88SJack F Vogel 		 */
87913705f88SJack F Vogel 		if (i >= timeout) {
8800ac6dfecSJack F Vogel 			DEBUGOUT("SWESMBI Software EEPROM semaphore "
88113705f88SJack F Vogel 			         "not granted.\n");
88213705f88SJack F Vogel 			ixgbe_release_eeprom_semaphore(hw);
88313705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
88413705f88SJack F Vogel 		}
8850ac6dfecSJack F Vogel 	} else {
8860ac6dfecSJack F Vogel 		DEBUGOUT("Software semaphore SMBI between device drivers "
8870ac6dfecSJack F Vogel 		         "not granted.\n");
88813705f88SJack F Vogel 	}
88913705f88SJack F Vogel 
89013705f88SJack F Vogel 	return status;
89113705f88SJack F Vogel }
89213705f88SJack F Vogel 
89313705f88SJack F Vogel /**
89413705f88SJack F Vogel  *  ixgbe_release_eeprom_semaphore - Release hardware semaphore
89513705f88SJack F Vogel  *  @hw: pointer to hardware structure
89613705f88SJack F Vogel  *
89713705f88SJack F Vogel  *  This function clears hardware semaphore bits.
89813705f88SJack F Vogel  **/
89913705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
90013705f88SJack F Vogel {
90113705f88SJack F Vogel 	u32 swsm;
90213705f88SJack F Vogel 
9032969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_release_eeprom_semaphore");
9042969bf0eSJack F Vogel 
90513705f88SJack F Vogel 	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
90613705f88SJack F Vogel 
90713705f88SJack F Vogel 	/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
90813705f88SJack F Vogel 	swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI);
90913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
9109ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
91113705f88SJack F Vogel }
91213705f88SJack F Vogel 
91313705f88SJack F Vogel /**
91413705f88SJack F Vogel  *  ixgbe_ready_eeprom - Polls for EEPROM ready
91513705f88SJack F Vogel  *  @hw: pointer to hardware structure
91613705f88SJack F Vogel  **/
91713705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
91813705f88SJack F Vogel {
91913705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
92013705f88SJack F Vogel 	u16 i;
92113705f88SJack F Vogel 	u8 spi_stat_reg;
92213705f88SJack F Vogel 
9232969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_ready_eeprom");
9242969bf0eSJack F Vogel 
92513705f88SJack F Vogel 	/*
92613705f88SJack F Vogel 	 * Read "Status Register" repeatedly until the LSB is cleared.  The
92713705f88SJack F Vogel 	 * EEPROM will signal that the command has been completed by clearing
92813705f88SJack F Vogel 	 * bit 0 of the internal status register.  If it's not cleared within
92913705f88SJack F Vogel 	 * 5 milliseconds, then error out.
93013705f88SJack F Vogel 	 */
93113705f88SJack F Vogel 	for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) {
93213705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI,
93313705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
93413705f88SJack F Vogel 		spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8);
93513705f88SJack F Vogel 		if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI))
93613705f88SJack F Vogel 			break;
93713705f88SJack F Vogel 
93813705f88SJack F Vogel 		usec_delay(5);
93913705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
94013705f88SJack F Vogel 	};
94113705f88SJack F Vogel 
94213705f88SJack F Vogel 	/*
94313705f88SJack F Vogel 	 * On some parts, SPI write time could vary from 0-20mSec on 3.3V
94413705f88SJack F Vogel 	 * devices (and only 0-5mSec on 5V devices)
94513705f88SJack F Vogel 	 */
94613705f88SJack F Vogel 	if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
94713705f88SJack F Vogel 		DEBUGOUT("SPI EEPROM Status error\n");
94813705f88SJack F Vogel 		status = IXGBE_ERR_EEPROM;
94913705f88SJack F Vogel 	}
95013705f88SJack F Vogel 
95113705f88SJack F Vogel 	return status;
95213705f88SJack F Vogel }
95313705f88SJack F Vogel 
95413705f88SJack F Vogel /**
95513705f88SJack F Vogel  *  ixgbe_standby_eeprom - Returns EEPROM to a "standby" state
95613705f88SJack F Vogel  *  @hw: pointer to hardware structure
95713705f88SJack F Vogel  **/
95813705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
95913705f88SJack F Vogel {
96013705f88SJack F Vogel 	u32 eec;
96113705f88SJack F Vogel 
9622969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_standby_eeprom");
9632969bf0eSJack F Vogel 
96413705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
96513705f88SJack F Vogel 
96613705f88SJack F Vogel 	/* Toggle CS to flush commands */
96713705f88SJack F Vogel 	eec |= IXGBE_EEC_CS;
96813705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
96913705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
97013705f88SJack F Vogel 	usec_delay(1);
97113705f88SJack F Vogel 	eec &= ~IXGBE_EEC_CS;
97213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
97313705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
97413705f88SJack F Vogel 	usec_delay(1);
97513705f88SJack F Vogel }
97613705f88SJack F Vogel 
97713705f88SJack F Vogel /**
97813705f88SJack F Vogel  *  ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM.
97913705f88SJack F Vogel  *  @hw: pointer to hardware structure
98013705f88SJack F Vogel  *  @data: data to send to the EEPROM
98113705f88SJack F Vogel  *  @count: number of bits to shift out
98213705f88SJack F Vogel  **/
98313705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
98413705f88SJack F Vogel                                         u16 count)
98513705f88SJack F Vogel {
98613705f88SJack F Vogel 	u32 eec;
98713705f88SJack F Vogel 	u32 mask;
98813705f88SJack F Vogel 	u32 i;
98913705f88SJack F Vogel 
9902969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_shift_out_eeprom_bits");
9912969bf0eSJack F Vogel 
99213705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
99313705f88SJack F Vogel 
99413705f88SJack F Vogel 	/*
99513705f88SJack F Vogel 	 * Mask is used to shift "count" bits of "data" out to the EEPROM
99613705f88SJack F Vogel 	 * one bit at a time.  Determine the starting bit based on count
99713705f88SJack F Vogel 	 */
99813705f88SJack F Vogel 	mask = 0x01 << (count - 1);
99913705f88SJack F Vogel 
100013705f88SJack F Vogel 	for (i = 0; i < count; i++) {
100113705f88SJack F Vogel 		/*
100213705f88SJack F Vogel 		 * A "1" is shifted out to the EEPROM by setting bit "DI" to a
100313705f88SJack F Vogel 		 * "1", and then raising and then lowering the clock (the SK
100413705f88SJack F Vogel 		 * bit controls the clock input to the EEPROM).  A "0" is
100513705f88SJack F Vogel 		 * shifted out to the EEPROM by setting "DI" to "0" and then
100613705f88SJack F Vogel 		 * raising and then lowering the clock.
100713705f88SJack F Vogel 		 */
100813705f88SJack F Vogel 		if (data & mask)
100913705f88SJack F Vogel 			eec |= IXGBE_EEC_DI;
101013705f88SJack F Vogel 		else
101113705f88SJack F Vogel 			eec &= ~IXGBE_EEC_DI;
101213705f88SJack F Vogel 
101313705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
101413705f88SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
101513705f88SJack F Vogel 
101613705f88SJack F Vogel 		usec_delay(1);
101713705f88SJack F Vogel 
101813705f88SJack F Vogel 		ixgbe_raise_eeprom_clk(hw, &eec);
101913705f88SJack F Vogel 		ixgbe_lower_eeprom_clk(hw, &eec);
102013705f88SJack F Vogel 
102113705f88SJack F Vogel 		/*
102213705f88SJack F Vogel 		 * Shift mask to signify next bit of data to shift in to the
102313705f88SJack F Vogel 		 * EEPROM
102413705f88SJack F Vogel 		 */
102513705f88SJack F Vogel 		mask = mask >> 1;
102613705f88SJack F Vogel 	};
102713705f88SJack F Vogel 
102813705f88SJack F Vogel 	/* We leave the "DI" bit set to "0" when we leave this routine. */
102913705f88SJack F Vogel 	eec &= ~IXGBE_EEC_DI;
103013705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
103113705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
103213705f88SJack F Vogel }
103313705f88SJack F Vogel 
103413705f88SJack F Vogel /**
103513705f88SJack F Vogel  *  ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
103613705f88SJack F Vogel  *  @hw: pointer to hardware structure
103713705f88SJack F Vogel  **/
103813705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
103913705f88SJack F Vogel {
104013705f88SJack F Vogel 	u32 eec;
104113705f88SJack F Vogel 	u32 i;
104213705f88SJack F Vogel 	u16 data = 0;
104313705f88SJack F Vogel 
10442969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_shift_in_eeprom_bits");
10452969bf0eSJack F Vogel 
104613705f88SJack F Vogel 	/*
104713705f88SJack F Vogel 	 * In order to read a register from the EEPROM, we need to shift
104813705f88SJack F Vogel 	 * 'count' bits in from the EEPROM. Bits are "shifted in" by raising
104913705f88SJack F Vogel 	 * the clock input to the EEPROM (setting the SK bit), and then reading
105013705f88SJack F Vogel 	 * the value of the "DO" bit.  During this "shifting in" process the
105113705f88SJack F Vogel 	 * "DI" bit should always be clear.
105213705f88SJack F Vogel 	 */
105313705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
105413705f88SJack F Vogel 
105513705f88SJack F Vogel 	eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
105613705f88SJack F Vogel 
105713705f88SJack F Vogel 	for (i = 0; i < count; i++) {
105813705f88SJack F Vogel 		data = data << 1;
105913705f88SJack F Vogel 		ixgbe_raise_eeprom_clk(hw, &eec);
106013705f88SJack F Vogel 
106113705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
106213705f88SJack F Vogel 
106313705f88SJack F Vogel 		eec &= ~(IXGBE_EEC_DI);
106413705f88SJack F Vogel 		if (eec & IXGBE_EEC_DO)
106513705f88SJack F Vogel 			data |= 1;
106613705f88SJack F Vogel 
106713705f88SJack F Vogel 		ixgbe_lower_eeprom_clk(hw, &eec);
106813705f88SJack F Vogel 	}
106913705f88SJack F Vogel 
107013705f88SJack F Vogel 	return data;
107113705f88SJack F Vogel }
107213705f88SJack F Vogel 
107313705f88SJack F Vogel /**
107413705f88SJack F Vogel  *  ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input.
107513705f88SJack F Vogel  *  @hw: pointer to hardware structure
107613705f88SJack F Vogel  *  @eec: EEC register's current value
107713705f88SJack F Vogel  **/
107813705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
107913705f88SJack F Vogel {
10802969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_raise_eeprom_clk");
10812969bf0eSJack F Vogel 
108213705f88SJack F Vogel 	/*
108313705f88SJack F Vogel 	 * Raise the clock input to the EEPROM
108413705f88SJack F Vogel 	 * (setting the SK bit), then delay
108513705f88SJack F Vogel 	 */
108613705f88SJack F Vogel 	*eec = *eec | IXGBE_EEC_SK;
108713705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
108813705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
108913705f88SJack F Vogel 	usec_delay(1);
109013705f88SJack F Vogel }
109113705f88SJack F Vogel 
109213705f88SJack F Vogel /**
109313705f88SJack F Vogel  *  ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input.
109413705f88SJack F Vogel  *  @hw: pointer to hardware structure
109513705f88SJack F Vogel  *  @eecd: EECD's current value
109613705f88SJack F Vogel  **/
109713705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
109813705f88SJack F Vogel {
10992969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_lower_eeprom_clk");
11002969bf0eSJack F Vogel 
110113705f88SJack F Vogel 	/*
110213705f88SJack F Vogel 	 * Lower the clock input to the EEPROM (clearing the SK bit), then
110313705f88SJack F Vogel 	 * delay
110413705f88SJack F Vogel 	 */
110513705f88SJack F Vogel 	*eec = *eec & ~IXGBE_EEC_SK;
110613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
110713705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
110813705f88SJack F Vogel 	usec_delay(1);
110913705f88SJack F Vogel }
111013705f88SJack F Vogel 
111113705f88SJack F Vogel /**
111213705f88SJack F Vogel  *  ixgbe_release_eeprom - Release EEPROM, release semaphores
111313705f88SJack F Vogel  *  @hw: pointer to hardware structure
111413705f88SJack F Vogel  **/
111513705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
111613705f88SJack F Vogel {
111713705f88SJack F Vogel 	u32 eec;
111813705f88SJack F Vogel 
11192969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_release_eeprom");
11202969bf0eSJack F Vogel 
112113705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
112213705f88SJack F Vogel 
112313705f88SJack F Vogel 	eec |= IXGBE_EEC_CS;  /* Pull CS high */
112413705f88SJack F Vogel 	eec &= ~IXGBE_EEC_SK; /* Lower SCK */
112513705f88SJack F Vogel 
112613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
112713705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
112813705f88SJack F Vogel 
112913705f88SJack F Vogel 	usec_delay(1);
113013705f88SJack F Vogel 
113113705f88SJack F Vogel 	/* Stop requesting EEPROM access */
113213705f88SJack F Vogel 	eec &= ~IXGBE_EEC_REQ;
113313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
113413705f88SJack F Vogel 
113513705f88SJack F Vogel 	ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
1136d8602bb9SJack F Vogel 
1137d8602bb9SJack F Vogel 	/* Delay before attempt to obtain semaphore again to allow FW access */
1138d8602bb9SJack F Vogel 	msec_delay(hw->eeprom.semaphore_delay);
113913705f88SJack F Vogel }
114013705f88SJack F Vogel 
114113705f88SJack F Vogel /**
11422969bf0eSJack F Vogel  *  ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
114313705f88SJack F Vogel  *  @hw: pointer to hardware structure
114413705f88SJack F Vogel  **/
11452969bf0eSJack F Vogel u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
114613705f88SJack F Vogel {
114713705f88SJack F Vogel 	u16 i;
114813705f88SJack F Vogel 	u16 j;
114913705f88SJack F Vogel 	u16 checksum = 0;
115013705f88SJack F Vogel 	u16 length = 0;
115113705f88SJack F Vogel 	u16 pointer = 0;
115213705f88SJack F Vogel 	u16 word = 0;
115313705f88SJack F Vogel 
11542969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic");
11552969bf0eSJack F Vogel 
115613705f88SJack F Vogel 	/* Include 0x0-0x3F in the checksum */
115713705f88SJack F Vogel 	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
11589ca4041bSJack F Vogel 		if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) {
115913705f88SJack F Vogel 			DEBUGOUT("EEPROM read failed\n");
116013705f88SJack F Vogel 			break;
116113705f88SJack F Vogel 		}
116213705f88SJack F Vogel 		checksum += word;
116313705f88SJack F Vogel 	}
116413705f88SJack F Vogel 
116513705f88SJack F Vogel 	/* Include all data from pointers except for the fw pointer */
116613705f88SJack F Vogel 	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
11679ca4041bSJack F Vogel 		hw->eeprom.ops.read(hw, i, &pointer);
116813705f88SJack F Vogel 
116913705f88SJack F Vogel 		/* Make sure the pointer seems valid */
117013705f88SJack F Vogel 		if (pointer != 0xFFFF && pointer != 0) {
11719ca4041bSJack F Vogel 			hw->eeprom.ops.read(hw, pointer, &length);
117213705f88SJack F Vogel 
117313705f88SJack F Vogel 			if (length != 0xFFFF && length != 0) {
117413705f88SJack F Vogel 				for (j = pointer+1; j <= pointer+length; j++) {
11759ca4041bSJack F Vogel 					hw->eeprom.ops.read(hw, j, &word);
117613705f88SJack F Vogel 					checksum += word;
117713705f88SJack F Vogel 				}
117813705f88SJack F Vogel 			}
117913705f88SJack F Vogel 		}
118013705f88SJack F Vogel 	}
118113705f88SJack F Vogel 
118213705f88SJack F Vogel 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
118313705f88SJack F Vogel 
118413705f88SJack F Vogel 	return checksum;
118513705f88SJack F Vogel }
118613705f88SJack F Vogel 
118713705f88SJack F Vogel /**
118813705f88SJack F Vogel  *  ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
118913705f88SJack F Vogel  *  @hw: pointer to hardware structure
119013705f88SJack F Vogel  *  @checksum_val: calculated checksum
119113705f88SJack F Vogel  *
119213705f88SJack F Vogel  *  Performs checksum calculation and validates the EEPROM checksum.  If the
119313705f88SJack F Vogel  *  caller does not need checksum_val, the value can be NULL.
119413705f88SJack F Vogel  **/
119513705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
119613705f88SJack F Vogel                                            u16 *checksum_val)
119713705f88SJack F Vogel {
119813705f88SJack F Vogel 	s32 status;
119913705f88SJack F Vogel 	u16 checksum;
120013705f88SJack F Vogel 	u16 read_checksum = 0;
120113705f88SJack F Vogel 
12022969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic");
12032969bf0eSJack F Vogel 
120413705f88SJack F Vogel 	/*
120513705f88SJack F Vogel 	 * Read the first word from the EEPROM. If this times out or fails, do
120613705f88SJack F Vogel 	 * not continue or we could be in for a very long wait while every
120713705f88SJack F Vogel 	 * EEPROM read fails
120813705f88SJack F Vogel 	 */
12099ca4041bSJack F Vogel 	status = hw->eeprom.ops.read(hw, 0, &checksum);
121013705f88SJack F Vogel 
121113705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
12122969bf0eSJack F Vogel 		checksum = hw->eeprom.ops.calc_checksum(hw);
121313705f88SJack F Vogel 
12149ca4041bSJack F Vogel 		hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
121513705f88SJack F Vogel 
121613705f88SJack F Vogel 		/*
121713705f88SJack F Vogel 		 * Verify read checksum from EEPROM is the same as
121813705f88SJack F Vogel 		 * calculated checksum
121913705f88SJack F Vogel 		 */
12209ca4041bSJack F Vogel 		if (read_checksum != checksum)
122113705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM_CHECKSUM;
122213705f88SJack F Vogel 
122313705f88SJack F Vogel 		/* If the user cares, return the calculated checksum */
12249ca4041bSJack F Vogel 		if (checksum_val)
122513705f88SJack F Vogel 			*checksum_val = checksum;
122613705f88SJack F Vogel 	} else {
122713705f88SJack F Vogel 		DEBUGOUT("EEPROM read failed\n");
122813705f88SJack F Vogel 	}
122913705f88SJack F Vogel 
123013705f88SJack F Vogel 	return status;
123113705f88SJack F Vogel }
123213705f88SJack F Vogel 
123313705f88SJack F Vogel /**
12349ca4041bSJack F Vogel  *  ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum
123513705f88SJack F Vogel  *  @hw: pointer to hardware structure
123613705f88SJack F Vogel  **/
123713705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
123813705f88SJack F Vogel {
123913705f88SJack F Vogel 	s32 status;
124013705f88SJack F Vogel 	u16 checksum;
124113705f88SJack F Vogel 
12422969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_update_eeprom_checksum_generic");
12432969bf0eSJack F Vogel 
124413705f88SJack F Vogel 	/*
124513705f88SJack F Vogel 	 * Read the first word from the EEPROM. If this times out or fails, do
124613705f88SJack F Vogel 	 * not continue or we could be in for a very long wait while every
124713705f88SJack F Vogel 	 * EEPROM read fails
124813705f88SJack F Vogel 	 */
12499ca4041bSJack F Vogel 	status = hw->eeprom.ops.read(hw, 0, &checksum);
125013705f88SJack F Vogel 
125113705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
12522969bf0eSJack F Vogel 		checksum = hw->eeprom.ops.calc_checksum(hw);
12539ca4041bSJack F Vogel 		status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
125413705f88SJack F Vogel 		                              checksum);
125513705f88SJack F Vogel 	} else {
125613705f88SJack F Vogel 		DEBUGOUT("EEPROM read failed\n");
125713705f88SJack F Vogel 	}
125813705f88SJack F Vogel 
125913705f88SJack F Vogel 	return status;
126013705f88SJack F Vogel }
126113705f88SJack F Vogel 
126213705f88SJack F Vogel /**
126313705f88SJack F Vogel  *  ixgbe_validate_mac_addr - Validate MAC address
126413705f88SJack F Vogel  *  @mac_addr: pointer to MAC address.
126513705f88SJack F Vogel  *
126613705f88SJack F Vogel  *  Tests a MAC address to ensure it is a valid Individual Address
126713705f88SJack F Vogel  **/
126813705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr)
126913705f88SJack F Vogel {
127013705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
127113705f88SJack F Vogel 
12722969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_validate_mac_addr");
12732969bf0eSJack F Vogel 
127413705f88SJack F Vogel 	/* Make sure it is not a multicast address */
127513705f88SJack F Vogel 	if (IXGBE_IS_MULTICAST(mac_addr)) {
127613705f88SJack F Vogel 		DEBUGOUT("MAC address is multicast\n");
127713705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
127813705f88SJack F Vogel 	/* Not a broadcast address */
127913705f88SJack F Vogel 	} else if (IXGBE_IS_BROADCAST(mac_addr)) {
128013705f88SJack F Vogel 		DEBUGOUT("MAC address is broadcast\n");
128113705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
128213705f88SJack F Vogel 	/* Reject the zero address */
128313705f88SJack F Vogel 	} else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
128413705f88SJack F Vogel 	           mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
128513705f88SJack F Vogel 		DEBUGOUT("MAC address is all zeros\n");
128613705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
128713705f88SJack F Vogel 	}
128813705f88SJack F Vogel 	return status;
128913705f88SJack F Vogel }
129013705f88SJack F Vogel 
129113705f88SJack F Vogel /**
12929ca4041bSJack F Vogel  *  ixgbe_set_rar_generic - Set Rx address register
129313705f88SJack F Vogel  *  @hw: pointer to hardware structure
129413705f88SJack F Vogel  *  @index: Receive address register to write
12959ca4041bSJack F Vogel  *  @addr: Address to put into receive address register
12969ca4041bSJack F Vogel  *  @vmdq: VMDq "set" or "pool" index
129713705f88SJack F Vogel  *  @enable_addr: set flag that address is active
129813705f88SJack F Vogel  *
129913705f88SJack F Vogel  *  Puts an ethernet address into a receive address register.
130013705f88SJack F Vogel  **/
13019ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
130213705f88SJack F Vogel                           u32 enable_addr)
130313705f88SJack F Vogel {
130413705f88SJack F Vogel 	u32 rar_low, rar_high;
13059ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
130613705f88SJack F Vogel 
13072969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_rar_generic");
13082969bf0eSJack F Vogel 
13099ca4041bSJack F Vogel 	/* setup VMDq pool selection before this RAR gets enabled */
13109ca4041bSJack F Vogel 	hw->mac.ops.set_vmdq(hw, index, vmdq);
13119ca4041bSJack F Vogel 
13129ca4041bSJack F Vogel 	/* Make sure we are using a valid rar index range */
13139ca4041bSJack F Vogel 	if (index < rar_entries) {
131413705f88SJack F Vogel 		/*
13159ca4041bSJack F Vogel 		 * HW expects these in little endian so we reverse the byte
13169ca4041bSJack F Vogel 		 * order from network order (big endian) to little endian
131713705f88SJack F Vogel 		 */
131813705f88SJack F Vogel 		rar_low = ((u32)addr[0] |
131913705f88SJack F Vogel 		           ((u32)addr[1] << 8) |
132013705f88SJack F Vogel 		           ((u32)addr[2] << 16) |
132113705f88SJack F Vogel 		           ((u32)addr[3] << 24));
13229ca4041bSJack F Vogel 		/*
13239ca4041bSJack F Vogel 		 * Some parts put the VMDq setting in the extra RAH bits,
13249ca4041bSJack F Vogel 		 * so save everything except the lower 16 bits that hold part
13259ca4041bSJack F Vogel 		 * of the address and the address valid bit.
13269ca4041bSJack F Vogel 		 */
13279ca4041bSJack F Vogel 		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
13289ca4041bSJack F Vogel 		rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
13299ca4041bSJack F Vogel 		rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
133013705f88SJack F Vogel 
133113705f88SJack F Vogel 		if (enable_addr != 0)
133213705f88SJack F Vogel 			rar_high |= IXGBE_RAH_AV;
133313705f88SJack F Vogel 
133413705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
133513705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
13369ca4041bSJack F Vogel 	} else {
13375b7f4cedSJack F Vogel 		DEBUGOUT1("RAR index %d is out of range.\n", index);
13389ca4041bSJack F Vogel 	}
133913705f88SJack F Vogel 
134013705f88SJack F Vogel 	return IXGBE_SUCCESS;
134113705f88SJack F Vogel }
134213705f88SJack F Vogel 
134313705f88SJack F Vogel /**
13445b7f4cedSJack F Vogel  *  ixgbe_clear_rar_generic - Remove Rx address register
13455b7f4cedSJack F Vogel  *  @hw: pointer to hardware structure
13465b7f4cedSJack F Vogel  *  @index: Receive address register to write
13475b7f4cedSJack F Vogel  *
13485b7f4cedSJack F Vogel  *  Clears an ethernet address from a receive address register.
13495b7f4cedSJack F Vogel  **/
13505b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
13515b7f4cedSJack F Vogel {
13525b7f4cedSJack F Vogel 	u32 rar_high;
13535b7f4cedSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
13545b7f4cedSJack F Vogel 
13552969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_clear_rar_generic");
13562969bf0eSJack F Vogel 
13575b7f4cedSJack F Vogel 	/* Make sure we are using a valid rar index range */
13585b7f4cedSJack F Vogel 	if (index < rar_entries) {
13595b7f4cedSJack F Vogel 		/*
13605b7f4cedSJack F Vogel 		 * Some parts put the VMDq setting in the extra RAH bits,
13615b7f4cedSJack F Vogel 		 * so save everything except the lower 16 bits that hold part
13625b7f4cedSJack F Vogel 		 * of the address and the address valid bit.
13635b7f4cedSJack F Vogel 		 */
13645b7f4cedSJack F Vogel 		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
13655b7f4cedSJack F Vogel 		rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
13665b7f4cedSJack F Vogel 
13675b7f4cedSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
13685b7f4cedSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
13695b7f4cedSJack F Vogel 	} else {
13705b7f4cedSJack F Vogel 		DEBUGOUT1("RAR index %d is out of range.\n", index);
13715b7f4cedSJack F Vogel 	}
13725b7f4cedSJack F Vogel 
13735b7f4cedSJack F Vogel 	/* clear VMDq pool/queue selection for this RAR */
13745b7f4cedSJack F Vogel 	hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
13755b7f4cedSJack F Vogel 
13765b7f4cedSJack F Vogel 	return IXGBE_SUCCESS;
13775b7f4cedSJack F Vogel }
13785b7f4cedSJack F Vogel 
13795b7f4cedSJack F Vogel /**
138013705f88SJack F Vogel  *  ixgbe_init_rx_addrs_generic - Initializes receive address filters.
138113705f88SJack F Vogel  *  @hw: pointer to hardware structure
138213705f88SJack F Vogel  *
138313705f88SJack F Vogel  *  Places the MAC address in receive address register 0 and clears the rest
13849ca4041bSJack F Vogel  *  of the receive address registers. Clears the multicast table. Assumes
138513705f88SJack F Vogel  *  the receiver is in reset when the routine is called.
138613705f88SJack F Vogel  **/
138713705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
138813705f88SJack F Vogel {
138913705f88SJack F Vogel 	u32 i;
13909ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
139113705f88SJack F Vogel 
13922969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_rx_addrs_generic");
13932969bf0eSJack F Vogel 
139413705f88SJack F Vogel 	/*
139513705f88SJack F Vogel 	 * If the current mac address is valid, assume it is a software override
139613705f88SJack F Vogel 	 * to the permanent address.
139713705f88SJack F Vogel 	 * Otherwise, use the permanent address from the eeprom.
139813705f88SJack F Vogel 	 */
139913705f88SJack F Vogel 	if (ixgbe_validate_mac_addr(hw->mac.addr) ==
140013705f88SJack F Vogel 	    IXGBE_ERR_INVALID_MAC_ADDR) {
140113705f88SJack F Vogel 		/* Get the MAC address from the RAR0 for later reference */
14029ca4041bSJack F Vogel 		hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
140313705f88SJack F Vogel 
140413705f88SJack F Vogel 		DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
140513705f88SJack F Vogel 		          hw->mac.addr[0], hw->mac.addr[1],
140613705f88SJack F Vogel 		          hw->mac.addr[2]);
140713705f88SJack F Vogel 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
140813705f88SJack F Vogel 		          hw->mac.addr[4], hw->mac.addr[5]);
140913705f88SJack F Vogel 	} else {
141013705f88SJack F Vogel 		/* Setup the receive address. */
141113705f88SJack F Vogel 		DEBUGOUT("Overriding MAC Address in RAR[0]\n");
141213705f88SJack F Vogel 		DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
141313705f88SJack F Vogel 		          hw->mac.addr[0], hw->mac.addr[1],
141413705f88SJack F Vogel 		          hw->mac.addr[2]);
141513705f88SJack F Vogel 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
141613705f88SJack F Vogel 		          hw->mac.addr[4], hw->mac.addr[5]);
141713705f88SJack F Vogel 
14189ca4041bSJack F Vogel 		hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
141913705f88SJack F Vogel 	}
14209ca4041bSJack F Vogel 	hw->addr_ctrl.overflow_promisc = 0;
142113705f88SJack F Vogel 
142213705f88SJack F Vogel 	hw->addr_ctrl.rar_used_count = 1;
142313705f88SJack F Vogel 
142413705f88SJack F Vogel 	/* Zero out the other receive addresses. */
14259ca4041bSJack F Vogel 	DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1);
142613705f88SJack F Vogel 	for (i = 1; i < rar_entries; i++) {
142713705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
142813705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
142913705f88SJack F Vogel 	}
143013705f88SJack F Vogel 
143113705f88SJack F Vogel 	/* Clear the MTA */
143213705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use = 0;
143313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
143413705f88SJack F Vogel 
143513705f88SJack F Vogel 	DEBUGOUT(" Clearing MTA\n");
14369ca4041bSJack F Vogel 	for (i = 0; i < hw->mac.mcft_size; i++)
143713705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
143813705f88SJack F Vogel 
14395b7f4cedSJack F Vogel 	ixgbe_init_uta_tables(hw);
14405b7f4cedSJack F Vogel 
144113705f88SJack F Vogel 	return IXGBE_SUCCESS;
144213705f88SJack F Vogel }
144313705f88SJack F Vogel 
144413705f88SJack F Vogel /**
14459ca4041bSJack F Vogel  *  ixgbe_add_uc_addr - Adds a secondary unicast address.
14469ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
14479ca4041bSJack F Vogel  *  @addr: new address
14489ca4041bSJack F Vogel  *
14499ca4041bSJack F Vogel  *  Adds it to unused receive address register or goes into promiscuous mode.
14509ca4041bSJack F Vogel  **/
14519ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
14529ca4041bSJack F Vogel {
14539ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
14549ca4041bSJack F Vogel 	u32 rar;
14559ca4041bSJack F Vogel 
14562969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_add_uc_addr");
14572969bf0eSJack F Vogel 
14589ca4041bSJack F Vogel 	DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
14599ca4041bSJack F Vogel 	          addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
14609ca4041bSJack F Vogel 
14619ca4041bSJack F Vogel 	/*
14629ca4041bSJack F Vogel 	 * Place this address in the RAR if there is room,
14639ca4041bSJack F Vogel 	 * else put the controller into promiscuous mode
14649ca4041bSJack F Vogel 	 */
14659ca4041bSJack F Vogel 	if (hw->addr_ctrl.rar_used_count < rar_entries) {
14660ac6dfecSJack F Vogel 		rar = hw->addr_ctrl.rar_used_count;
14679ca4041bSJack F Vogel 		hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
14689ca4041bSJack F Vogel 		DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar);
14699ca4041bSJack F Vogel 		hw->addr_ctrl.rar_used_count++;
14709ca4041bSJack F Vogel 	} else {
14719ca4041bSJack F Vogel 		hw->addr_ctrl.overflow_promisc++;
14729ca4041bSJack F Vogel 	}
14739ca4041bSJack F Vogel 
14749ca4041bSJack F Vogel 	DEBUGOUT("ixgbe_add_uc_addr Complete\n");
14759ca4041bSJack F Vogel }
14769ca4041bSJack F Vogel 
14779ca4041bSJack F Vogel /**
14789ca4041bSJack F Vogel  *  ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
14799ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
14809ca4041bSJack F Vogel  *  @addr_list: the list of new addresses
14819ca4041bSJack F Vogel  *  @addr_count: number of addresses
14829ca4041bSJack F Vogel  *  @next: iterator function to walk the address list
14839ca4041bSJack F Vogel  *
14849ca4041bSJack F Vogel  *  The given list replaces any existing list.  Clears the secondary addrs from
14859ca4041bSJack F Vogel  *  receive address registers.  Uses unused receive address registers for the
14869ca4041bSJack F Vogel  *  first secondary addresses, and falls back to promiscuous mode as needed.
14879ca4041bSJack F Vogel  *
14889ca4041bSJack F Vogel  *  Drivers using secondary unicast addresses must set user_set_promisc when
14899ca4041bSJack F Vogel  *  manually putting the device into promiscuous mode.
14909ca4041bSJack F Vogel  **/
14919ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
14929ca4041bSJack F Vogel                                       u32 addr_count, ixgbe_mc_addr_itr next)
14939ca4041bSJack F Vogel {
14949ca4041bSJack F Vogel 	u8 *addr;
14959ca4041bSJack F Vogel 	u32 i;
14969ca4041bSJack F Vogel 	u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
14979ca4041bSJack F Vogel 	u32 uc_addr_in_use;
14989ca4041bSJack F Vogel 	u32 fctrl;
14999ca4041bSJack F Vogel 	u32 vmdq;
15009ca4041bSJack F Vogel 
15012969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_update_uc_addr_list_generic");
15022969bf0eSJack F Vogel 
15039ca4041bSJack F Vogel 	/*
15049ca4041bSJack F Vogel 	 * Clear accounting of old secondary address list,
15059ca4041bSJack F Vogel 	 * don't count RAR[0]
15069ca4041bSJack F Vogel 	 */
15070ac6dfecSJack F Vogel 	uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1;
15089ca4041bSJack F Vogel 	hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
15099ca4041bSJack F Vogel 	hw->addr_ctrl.overflow_promisc = 0;
15109ca4041bSJack F Vogel 
15119ca4041bSJack F Vogel 	/* Zero out the other receive addresses */
15122969bf0eSJack F Vogel 	DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1);
15132969bf0eSJack F Vogel 	for (i = 0; i < uc_addr_in_use; i++) {
15142969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0);
15152969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0);
15169ca4041bSJack F Vogel 	}
15179ca4041bSJack F Vogel 
15189ca4041bSJack F Vogel 	/* Add the new addresses */
15199ca4041bSJack F Vogel 	for (i = 0; i < addr_count; i++) {
15209ca4041bSJack F Vogel 		DEBUGOUT(" Adding the secondary addresses:\n");
15219ca4041bSJack F Vogel 		addr = next(hw, &addr_list, &vmdq);
15229ca4041bSJack F Vogel 		ixgbe_add_uc_addr(hw, addr, vmdq);
15239ca4041bSJack F Vogel 	}
15249ca4041bSJack F Vogel 
15259ca4041bSJack F Vogel 	if (hw->addr_ctrl.overflow_promisc) {
15269ca4041bSJack F Vogel 		/* enable promisc if not already in overflow or set by user */
15279ca4041bSJack F Vogel 		if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
15289ca4041bSJack F Vogel 			DEBUGOUT(" Entering address overflow promisc mode\n");
15299ca4041bSJack F Vogel 			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
15309ca4041bSJack F Vogel 			fctrl |= IXGBE_FCTRL_UPE;
15319ca4041bSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
15329ca4041bSJack F Vogel 		}
15339ca4041bSJack F Vogel 	} else {
15349ca4041bSJack F Vogel 		/* only disable if set by overflow, not by user */
15359ca4041bSJack F Vogel 		if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
15369ca4041bSJack F Vogel 			DEBUGOUT(" Leaving address overflow promisc mode\n");
15379ca4041bSJack F Vogel 			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
15389ca4041bSJack F Vogel 			fctrl &= ~IXGBE_FCTRL_UPE;
15399ca4041bSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
15409ca4041bSJack F Vogel 		}
15419ca4041bSJack F Vogel 	}
15429ca4041bSJack F Vogel 
15439ca4041bSJack F Vogel 	DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n");
15449ca4041bSJack F Vogel 	return IXGBE_SUCCESS;
15459ca4041bSJack F Vogel }
15469ca4041bSJack F Vogel 
15479ca4041bSJack F Vogel /**
154813705f88SJack F Vogel  *  ixgbe_mta_vector - Determines bit-vector in multicast table to set
154913705f88SJack F Vogel  *  @hw: pointer to hardware structure
155013705f88SJack F Vogel  *  @mc_addr: the multicast address
155113705f88SJack F Vogel  *
155213705f88SJack F Vogel  *  Extracts the 12 bits, from a multicast address, to determine which
155313705f88SJack F Vogel  *  bit-vector to set in the multicast table. The hardware uses 12 bits, from
155413705f88SJack F Vogel  *  incoming rx multicast addresses, to determine the bit-vector to check in
155513705f88SJack F Vogel  *  the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
15569ca4041bSJack F Vogel  *  by the MO field of the MCSTCTRL. The MO field is set during initialization
155713705f88SJack F Vogel  *  to mc_filter_type.
155813705f88SJack F Vogel  **/
155913705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
156013705f88SJack F Vogel {
156113705f88SJack F Vogel 	u32 vector = 0;
156213705f88SJack F Vogel 
15632969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_mta_vector");
15642969bf0eSJack F Vogel 
156513705f88SJack F Vogel 	switch (hw->mac.mc_filter_type) {
156613705f88SJack F Vogel 	case 0:   /* use bits [47:36] of the address */
156713705f88SJack F Vogel 		vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
156813705f88SJack F Vogel 		break;
156913705f88SJack F Vogel 	case 1:   /* use bits [46:35] of the address */
157013705f88SJack F Vogel 		vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
157113705f88SJack F Vogel 		break;
157213705f88SJack F Vogel 	case 2:   /* use bits [45:34] of the address */
157313705f88SJack F Vogel 		vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
157413705f88SJack F Vogel 		break;
157513705f88SJack F Vogel 	case 3:   /* use bits [43:32] of the address */
157613705f88SJack F Vogel 		vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
157713705f88SJack F Vogel 		break;
157813705f88SJack F Vogel 	default:  /* Invalid mc_filter_type */
157913705f88SJack F Vogel 		DEBUGOUT("MC filter type param set incorrectly\n");
158013705f88SJack F Vogel 		ASSERT(0);
158113705f88SJack F Vogel 		break;
158213705f88SJack F Vogel 	}
158313705f88SJack F Vogel 
158413705f88SJack F Vogel 	/* vector can only be 12-bits or boundary will be exceeded */
158513705f88SJack F Vogel 	vector &= 0xFFF;
158613705f88SJack F Vogel 	return vector;
158713705f88SJack F Vogel }
158813705f88SJack F Vogel 
158913705f88SJack F Vogel /**
159013705f88SJack F Vogel  *  ixgbe_set_mta - Set bit-vector in multicast table
159113705f88SJack F Vogel  *  @hw: pointer to hardware structure
159213705f88SJack F Vogel  *  @hash_value: Multicast address hash value
159313705f88SJack F Vogel  *
159413705f88SJack F Vogel  *  Sets the bit-vector in the multicast table.
159513705f88SJack F Vogel  **/
159613705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
159713705f88SJack F Vogel {
159813705f88SJack F Vogel 	u32 vector;
159913705f88SJack F Vogel 	u32 vector_bit;
160013705f88SJack F Vogel 	u32 vector_reg;
160113705f88SJack F Vogel 	u32 mta_reg;
160213705f88SJack F Vogel 
16032969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_mta");
16042969bf0eSJack F Vogel 
160513705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use++;
160613705f88SJack F Vogel 
160713705f88SJack F Vogel 	vector = ixgbe_mta_vector(hw, mc_addr);
160813705f88SJack F Vogel 	DEBUGOUT1(" bit-vector = 0x%03X\n", vector);
160913705f88SJack F Vogel 
161013705f88SJack F Vogel 	/*
161113705f88SJack F Vogel 	 * The MTA is a register array of 128 32-bit registers. It is treated
161213705f88SJack F Vogel 	 * like an array of 4096 bits.  We want to set bit
161313705f88SJack F Vogel 	 * BitArray[vector_value]. So we figure out what register the bit is
161413705f88SJack F Vogel 	 * in, read it, OR in the new bit, then write back the new value.  The
161513705f88SJack F Vogel 	 * register is determined by the upper 7 bits of the vector value and
161613705f88SJack F Vogel 	 * the bit within that register are determined by the lower 5 bits of
161713705f88SJack F Vogel 	 * the value.
161813705f88SJack F Vogel 	 */
161913705f88SJack F Vogel 	vector_reg = (vector >> 5) & 0x7F;
162013705f88SJack F Vogel 	vector_bit = vector & 0x1F;
162113705f88SJack F Vogel 	mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg));
162213705f88SJack F Vogel 	mta_reg |= (1 << vector_bit);
162313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
162413705f88SJack F Vogel }
162513705f88SJack F Vogel 
162613705f88SJack F Vogel /**
162713705f88SJack F Vogel  *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
162813705f88SJack F Vogel  *  @hw: pointer to hardware structure
162913705f88SJack F Vogel  *  @mc_addr_list: the list of new multicast addresses
163013705f88SJack F Vogel  *  @mc_addr_count: number of addresses
16319ca4041bSJack F Vogel  *  @next: iterator function to walk the multicast address list
163213705f88SJack F Vogel  *
163313705f88SJack F Vogel  *  The given list replaces any existing list. Clears the MC addrs from receive
16349ca4041bSJack F Vogel  *  address registers and the multicast table. Uses unused receive address
163513705f88SJack F Vogel  *  registers for the first multicast addresses, and hashes the rest into the
163613705f88SJack F Vogel  *  multicast table.
163713705f88SJack F Vogel  **/
163813705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
16399ca4041bSJack F Vogel                                       u32 mc_addr_count, ixgbe_mc_addr_itr next)
164013705f88SJack F Vogel {
164113705f88SJack F Vogel 	u32 i;
16429ca4041bSJack F Vogel 	u32 vmdq;
164313705f88SJack F Vogel 
16442969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_update_mc_addr_list_generic");
16452969bf0eSJack F Vogel 
164613705f88SJack F Vogel 	/*
164713705f88SJack F Vogel 	 * Set the new number of MC addresses that we are being requested to
164813705f88SJack F Vogel 	 * use.
164913705f88SJack F Vogel 	 */
165013705f88SJack F Vogel 	hw->addr_ctrl.num_mc_addrs = mc_addr_count;
165113705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use = 0;
165213705f88SJack F Vogel 
165313705f88SJack F Vogel 	/* Clear the MTA */
165413705f88SJack F Vogel 	DEBUGOUT(" Clearing MTA\n");
16559ca4041bSJack F Vogel 	for (i = 0; i < hw->mac.mcft_size; i++)
165613705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
165713705f88SJack F Vogel 
165813705f88SJack F Vogel 	/* Add the new addresses */
165913705f88SJack F Vogel 	for (i = 0; i < mc_addr_count; i++) {
166013705f88SJack F Vogel 		DEBUGOUT(" Adding the multicast addresses:\n");
16610ac6dfecSJack F Vogel 		ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq));
166213705f88SJack F Vogel 	}
166313705f88SJack F Vogel 
166413705f88SJack F Vogel 	/* Enable mta */
166513705f88SJack F Vogel 	if (hw->addr_ctrl.mta_in_use > 0)
166613705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
166713705f88SJack F Vogel 		                IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
166813705f88SJack F Vogel 
166913705f88SJack F Vogel 	DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n");
167013705f88SJack F Vogel 	return IXGBE_SUCCESS;
167113705f88SJack F Vogel }
167213705f88SJack F Vogel 
167313705f88SJack F Vogel /**
167413705f88SJack F Vogel  *  ixgbe_enable_mc_generic - Enable multicast address in RAR
167513705f88SJack F Vogel  *  @hw: pointer to hardware structure
167613705f88SJack F Vogel  *
167713705f88SJack F Vogel  *  Enables multicast address in RAR and the use of the multicast hash table.
167813705f88SJack F Vogel  **/
167913705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
168013705f88SJack F Vogel {
168113705f88SJack F Vogel 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
168213705f88SJack F Vogel 
16832969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_enable_mc_generic");
16842969bf0eSJack F Vogel 
168513705f88SJack F Vogel 	if (a->mta_in_use > 0)
168613705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
168713705f88SJack F Vogel 		                hw->mac.mc_filter_type);
168813705f88SJack F Vogel 
168913705f88SJack F Vogel 	return IXGBE_SUCCESS;
169013705f88SJack F Vogel }
169113705f88SJack F Vogel 
169213705f88SJack F Vogel /**
16939ca4041bSJack F Vogel  *  ixgbe_disable_mc_generic - Disable multicast address in RAR
169413705f88SJack F Vogel  *  @hw: pointer to hardware structure
169513705f88SJack F Vogel  *
169613705f88SJack F Vogel  *  Disables multicast address in RAR and the use of the multicast hash table.
169713705f88SJack F Vogel  **/
169813705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
169913705f88SJack F Vogel {
170013705f88SJack F Vogel 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
170113705f88SJack F Vogel 
17022969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_disable_mc_generic");
17032969bf0eSJack F Vogel 
170413705f88SJack F Vogel 	if (a->mta_in_use > 0)
170513705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
170613705f88SJack F Vogel 
170713705f88SJack F Vogel 	return IXGBE_SUCCESS;
170813705f88SJack F Vogel }
170913705f88SJack F Vogel 
17101b6e0dbaSJack F Vogel /**
17110ac6dfecSJack F Vogel  *  ixgbe_fc_enable_generic - Enable flow control
17121b6e0dbaSJack F Vogel  *  @hw: pointer to hardware structure
17130ac6dfecSJack F Vogel  *  @packetbuf_num: packet buffer number (0-7)
17141b6e0dbaSJack F Vogel  *
17150ac6dfecSJack F Vogel  *  Enable flow control according to the current settings.
17161b6e0dbaSJack F Vogel  **/
17170ac6dfecSJack F Vogel s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
17181b6e0dbaSJack F Vogel {
17191b6e0dbaSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
17200ac6dfecSJack F Vogel 	u32 mflcn_reg, fccfg_reg;
17210ac6dfecSJack F Vogel 	u32 reg;
1722d8602bb9SJack F Vogel 	u32 rx_pba_size;
17231b6e0dbaSJack F Vogel 
17240ac6dfecSJack F Vogel 	DEBUGFUNC("ixgbe_fc_enable_generic");
17251b6e0dbaSJack F Vogel 
17260ac6dfecSJack F Vogel 	/* Negotiate the fc mode to use */
17270ac6dfecSJack F Vogel 	ret_val = ixgbe_fc_autoneg(hw);
17280ac6dfecSJack F Vogel 	if (ret_val)
17290ac6dfecSJack F Vogel 		goto out;
17300ac6dfecSJack F Vogel 
17310ac6dfecSJack F Vogel 	/* Disable any previous flow control settings */
17320ac6dfecSJack F Vogel 	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
17330ac6dfecSJack F Vogel 	mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
17340ac6dfecSJack F Vogel 
17350ac6dfecSJack F Vogel 	fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
17360ac6dfecSJack F Vogel 	fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
17371b6e0dbaSJack F Vogel 
17381b6e0dbaSJack F Vogel 	/*
17391b6e0dbaSJack F Vogel 	 * The possible values of fc.current_mode are:
17401b6e0dbaSJack F Vogel 	 * 0: Flow control is completely disabled
17411b6e0dbaSJack F Vogel 	 * 1: Rx flow control is enabled (we can receive pause frames,
17421b6e0dbaSJack F Vogel 	 *    but not send pause frames).
17431b6e0dbaSJack F Vogel 	 * 2: Tx flow control is enabled (we can send pause frames but
17441b6e0dbaSJack F Vogel 	 *    we do not support receiving pause frames).
17451b6e0dbaSJack F Vogel 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
17461b6e0dbaSJack F Vogel 	 * other: Invalid.
17471b6e0dbaSJack F Vogel 	 */
17481b6e0dbaSJack F Vogel 	switch (hw->fc.current_mode) {
17491b6e0dbaSJack F Vogel 	case ixgbe_fc_none:
17500ac6dfecSJack F Vogel 		/* Flow control is disabled by software override or autoneg.
17510ac6dfecSJack F Vogel 		 * The code below will actually disable it in the HW.
17520ac6dfecSJack F Vogel 		 */
17531b6e0dbaSJack F Vogel 		break;
17541b6e0dbaSJack F Vogel 	case ixgbe_fc_rx_pause:
17551b6e0dbaSJack F Vogel 		/*
17561b6e0dbaSJack F Vogel 		 * Rx Flow control is enabled and Tx Flow control is
17571b6e0dbaSJack F Vogel 		 * disabled by software override. Since there really
17581b6e0dbaSJack F Vogel 		 * isn't a way to advertise that we are capable of RX
17591b6e0dbaSJack F Vogel 		 * Pause ONLY, we will advertise that we support both
17601b6e0dbaSJack F Vogel 		 * symmetric and asymmetric Rx PAUSE.  Later, we will
17611b6e0dbaSJack F Vogel 		 * disable the adapter's ability to send PAUSE frames.
17621b6e0dbaSJack F Vogel 		 */
17630ac6dfecSJack F Vogel 		mflcn_reg |= IXGBE_MFLCN_RFCE;
17641b6e0dbaSJack F Vogel 		break;
17651b6e0dbaSJack F Vogel 	case ixgbe_fc_tx_pause:
17661b6e0dbaSJack F Vogel 		/*
17671b6e0dbaSJack F Vogel 		 * Tx Flow control is enabled, and Rx Flow control is
17681b6e0dbaSJack F Vogel 		 * disabled by software override.
17691b6e0dbaSJack F Vogel 		 */
17700ac6dfecSJack F Vogel 		fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
17711b6e0dbaSJack F Vogel 		break;
17721b6e0dbaSJack F Vogel 	case ixgbe_fc_full:
17731b6e0dbaSJack F Vogel 		/* Flow control (both Rx and Tx) is enabled by SW override. */
17740ac6dfecSJack F Vogel 		mflcn_reg |= IXGBE_MFLCN_RFCE;
17750ac6dfecSJack F Vogel 		fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
17761b6e0dbaSJack F Vogel 		break;
17771b6e0dbaSJack F Vogel 	default:
17781b6e0dbaSJack F Vogel 		DEBUGOUT("Flow control param set incorrectly\n");
17792969bf0eSJack F Vogel 		ret_val = IXGBE_ERR_CONFIG;
17801b6e0dbaSJack F Vogel 		goto out;
17811b6e0dbaSJack F Vogel 		break;
17821b6e0dbaSJack F Vogel 	}
17831b6e0dbaSJack F Vogel 
17840ac6dfecSJack F Vogel 	/* Set 802.3x based flow control settings. */
17850ac6dfecSJack F Vogel 	mflcn_reg |= IXGBE_MFLCN_DPF;
17860ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
17870ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
17881b6e0dbaSJack F Vogel 
1789d8602bb9SJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_MTQC);
1790d8602bb9SJack F Vogel 	/* Thresholds are different for link flow control when in DCB mode */
1791d8602bb9SJack F Vogel 	if (reg & IXGBE_MTQC_RT_ENA) {
1792d8602bb9SJack F Vogel 		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
1793d8602bb9SJack F Vogel 
1794d8602bb9SJack F Vogel 		/* Always disable XON for LFC when in DCB mode */
1795d8602bb9SJack F Vogel 		reg = (rx_pba_size >> 5) & 0xFFE0;
1796d8602bb9SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg);
1797d8602bb9SJack F Vogel 
1798d8602bb9SJack F Vogel 		reg = (rx_pba_size >> 2) & 0xFFE0;
1799d8602bb9SJack F Vogel 		if (hw->fc.current_mode & ixgbe_fc_tx_pause)
1800d8602bb9SJack F Vogel 			reg |= IXGBE_FCRTH_FCEN;
1801d8602bb9SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), reg);
1802d8602bb9SJack F Vogel 	} else {
1803d8602bb9SJack F Vogel 		/* Set up and enable Rx high/low water mark thresholds,
1804d8602bb9SJack F Vogel 		 * enable XON. */
18050ac6dfecSJack F Vogel 		if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
18060ac6dfecSJack F Vogel 			if (hw->fc.send_xon) {
1807d8602bb9SJack F Vogel 				IXGBE_WRITE_REG(hw,
1808d8602bb9SJack F Vogel 				              IXGBE_FCRTL_82599(packetbuf_num),
1809d8602bb9SJack F Vogel 				              (hw->fc.low_water |
1810d8602bb9SJack F Vogel 				              IXGBE_FCRTL_XONE));
18110ac6dfecSJack F Vogel 			} else {
1812d8602bb9SJack F Vogel 				IXGBE_WRITE_REG(hw,
1813d8602bb9SJack F Vogel 				              IXGBE_FCRTL_82599(packetbuf_num),
18140ac6dfecSJack F Vogel 				              hw->fc.low_water);
18151b6e0dbaSJack F Vogel 			}
18161b6e0dbaSJack F Vogel 
18170ac6dfecSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num),
18180ac6dfecSJack F Vogel 			               (hw->fc.high_water | IXGBE_FCRTH_FCEN));
18190ac6dfecSJack F Vogel 		}
1820d8602bb9SJack F Vogel 	}
18210ac6dfecSJack F Vogel 
18220ac6dfecSJack F Vogel 	/* Configure pause time (2 TCs per register) */
1823d8602bb9SJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
18240ac6dfecSJack F Vogel 	if ((packetbuf_num & 1) == 0)
18250ac6dfecSJack F Vogel 		reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
18260ac6dfecSJack F Vogel 	else
18270ac6dfecSJack F Vogel 		reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
18280ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
18290ac6dfecSJack F Vogel 
18300ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
18310ac6dfecSJack F Vogel 
18320ac6dfecSJack F Vogel out:
18330ac6dfecSJack F Vogel 	return ret_val;
18340ac6dfecSJack F Vogel }
18350ac6dfecSJack F Vogel 
18360ac6dfecSJack F Vogel /**
18370ac6dfecSJack F Vogel  *  ixgbe_fc_autoneg - Configure flow control
18380ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
18390ac6dfecSJack F Vogel  *
18400ac6dfecSJack F Vogel  *  Compares our advertised flow control capabilities to those advertised by
18410ac6dfecSJack F Vogel  *  our link partner, and determines the proper flow control mode to use.
18420ac6dfecSJack F Vogel  **/
18430ac6dfecSJack F Vogel s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
18440ac6dfecSJack F Vogel {
18450ac6dfecSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
18460ac6dfecSJack F Vogel 	ixgbe_link_speed speed;
18470ac6dfecSJack F Vogel 	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
18482969bf0eSJack F Vogel 	u32 links2, anlp1_reg, autoc_reg, links;
18490ac6dfecSJack F Vogel 	bool link_up;
18500ac6dfecSJack F Vogel 
18510ac6dfecSJack F Vogel 	DEBUGFUNC("ixgbe_fc_autoneg");
18520ac6dfecSJack F Vogel 
18530ac6dfecSJack F Vogel 	/*
18540ac6dfecSJack F Vogel 	 * AN should have completed when the cable was plugged in.
18550ac6dfecSJack F Vogel 	 * Look for reasons to bail out.  Bail out if:
18560ac6dfecSJack F Vogel 	 * - FC autoneg is disabled, or if
18572969bf0eSJack F Vogel 	 * - link is not up.
18580ac6dfecSJack F Vogel 	 *
18592969bf0eSJack F Vogel 	 * Since we're being called from an LSC, link is already known to be up.
18600ac6dfecSJack F Vogel 	 * So use link_up_wait_to_complete=FALSE.
18610ac6dfecSJack F Vogel 	 */
18620ac6dfecSJack F Vogel 	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
18630ac6dfecSJack F Vogel 
18642969bf0eSJack F Vogel 	if (hw->fc.disable_fc_autoneg || (!link_up)) {
18652969bf0eSJack F Vogel 		hw->fc.fc_was_autonegged = FALSE;
18662969bf0eSJack F Vogel 		hw->fc.current_mode = hw->fc.requested_mode;
18672969bf0eSJack F Vogel 		goto out;
18682969bf0eSJack F Vogel 	}
18692969bf0eSJack F Vogel 
18702969bf0eSJack F Vogel 	/*
18712969bf0eSJack F Vogel 	 * On backplane, bail out if
18722969bf0eSJack F Vogel 	 * - backplane autoneg was not completed, or if
18732969bf0eSJack F Vogel 	 * - we are 82599 and link partner is not AN enabled
18742969bf0eSJack F Vogel 	 */
18752969bf0eSJack F Vogel 	if (hw->phy.media_type == ixgbe_media_type_backplane) {
18762969bf0eSJack F Vogel 		links = IXGBE_READ_REG(hw, IXGBE_LINKS);
18772969bf0eSJack F Vogel 		if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
18782969bf0eSJack F Vogel 			hw->fc.fc_was_autonegged = FALSE;
18792969bf0eSJack F Vogel 			hw->fc.current_mode = hw->fc.requested_mode;
18802969bf0eSJack F Vogel 			goto out;
18812969bf0eSJack F Vogel 		}
18822969bf0eSJack F Vogel 
18832969bf0eSJack F Vogel 		if (hw->mac.type == ixgbe_mac_82599EB) {
18842969bf0eSJack F Vogel 			links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
18852969bf0eSJack F Vogel 			if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
18862969bf0eSJack F Vogel 				hw->fc.fc_was_autonegged = FALSE;
18872969bf0eSJack F Vogel 				hw->fc.current_mode = hw->fc.requested_mode;
18882969bf0eSJack F Vogel 				goto out;
18892969bf0eSJack F Vogel 			}
18902969bf0eSJack F Vogel 		}
18912969bf0eSJack F Vogel 	}
18922969bf0eSJack F Vogel 
18932969bf0eSJack F Vogel 	/*
18942969bf0eSJack F Vogel 	 * On multispeed fiber at 1g, bail out if
18952969bf0eSJack F Vogel 	 * - link is up but AN did not complete, or if
18962969bf0eSJack F Vogel 	 * - link is up and AN completed but timed out
18972969bf0eSJack F Vogel 	 */
18982969bf0eSJack F Vogel 	if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) {
18992969bf0eSJack F Vogel 		linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
19002969bf0eSJack F Vogel 		if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
19010ac6dfecSJack F Vogel 		    ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
19020ac6dfecSJack F Vogel 			hw->fc.fc_was_autonegged = FALSE;
19030ac6dfecSJack F Vogel 			hw->fc.current_mode = hw->fc.requested_mode;
19042969bf0eSJack F Vogel 			goto out;
19052969bf0eSJack F Vogel 		}
19062969bf0eSJack F Vogel 	}
19072969bf0eSJack F Vogel 
19082969bf0eSJack F Vogel 	/*
19092969bf0eSJack F Vogel 	 * Bail out on
19102969bf0eSJack F Vogel 	 * - copper or CX4 adapters
19112969bf0eSJack F Vogel 	 * - fiber adapters running at 10gig
19122969bf0eSJack F Vogel 	 */
19132969bf0eSJack F Vogel 	if ((hw->phy.media_type == ixgbe_media_type_copper) ||
19142969bf0eSJack F Vogel 	     (hw->phy.media_type == ixgbe_media_type_cx4) ||
19152969bf0eSJack F Vogel 	     ((hw->phy.media_type == ixgbe_media_type_fiber) &&
19162969bf0eSJack F Vogel 	     (speed == IXGBE_LINK_SPEED_10GB_FULL))) {
19172969bf0eSJack F Vogel 		hw->fc.fc_was_autonegged = FALSE;
19182969bf0eSJack F Vogel 		hw->fc.current_mode = hw->fc.requested_mode;
19191b6e0dbaSJack F Vogel 		goto out;
19201b6e0dbaSJack F Vogel 	}
19211b6e0dbaSJack F Vogel 
19221b6e0dbaSJack F Vogel 	/*
19231b6e0dbaSJack F Vogel 	 * Read the AN advertisement and LP ability registers and resolve
19241b6e0dbaSJack F Vogel 	 * local flow control settings accordingly
19251b6e0dbaSJack F Vogel 	 */
19262969bf0eSJack F Vogel 	if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
19272969bf0eSJack F Vogel 	    (hw->phy.media_type != ixgbe_media_type_backplane)) {
19281b6e0dbaSJack F Vogel 		pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
19291b6e0dbaSJack F Vogel 		pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
19301b6e0dbaSJack F Vogel 		if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
19311b6e0dbaSJack F Vogel 		    (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
19321b6e0dbaSJack F Vogel 			/*
19331b6e0dbaSJack F Vogel 			 * Now we need to check if the user selected Rx ONLY
19341b6e0dbaSJack F Vogel 			 * of pause frames.  In this case, we had to advertise
19351b6e0dbaSJack F Vogel 			 * FULL flow control because we could not advertise RX
19361b6e0dbaSJack F Vogel 			 * ONLY. Hence, we must now check to see if we need to
19371b6e0dbaSJack F Vogel 			 * turn OFF the TRANSMISSION of PAUSE frames.
19381b6e0dbaSJack F Vogel 			 */
19391b6e0dbaSJack F Vogel 			if (hw->fc.requested_mode == ixgbe_fc_full) {
19401b6e0dbaSJack F Vogel 				hw->fc.current_mode = ixgbe_fc_full;
19411b6e0dbaSJack F Vogel 				DEBUGOUT("Flow Control = FULL.\n");
19421b6e0dbaSJack F Vogel 			} else {
19431b6e0dbaSJack F Vogel 				hw->fc.current_mode = ixgbe_fc_rx_pause;
19442969bf0eSJack F Vogel 				DEBUGOUT("Flow Control=RX PAUSE frames only\n");
19451b6e0dbaSJack F Vogel 			}
19461b6e0dbaSJack F Vogel 		} else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
19471b6e0dbaSJack F Vogel 			   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
19481b6e0dbaSJack F Vogel 			   (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
19491b6e0dbaSJack F Vogel 			   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
19501b6e0dbaSJack F Vogel 			hw->fc.current_mode = ixgbe_fc_tx_pause;
19511b6e0dbaSJack F Vogel 			DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
19521b6e0dbaSJack F Vogel 		} else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
19531b6e0dbaSJack F Vogel 			   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
19541b6e0dbaSJack F Vogel 			   !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
19551b6e0dbaSJack F Vogel 			   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
19561b6e0dbaSJack F Vogel 			hw->fc.current_mode = ixgbe_fc_rx_pause;
19571b6e0dbaSJack F Vogel 			DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
19581b6e0dbaSJack F Vogel 		} else {
19591b6e0dbaSJack F Vogel 			hw->fc.current_mode = ixgbe_fc_none;
19601b6e0dbaSJack F Vogel 			DEBUGOUT("Flow Control = NONE.\n");
19611b6e0dbaSJack F Vogel 		}
19622969bf0eSJack F Vogel 	}
19631b6e0dbaSJack F Vogel 
19642969bf0eSJack F Vogel 	if (hw->phy.media_type == ixgbe_media_type_backplane) {
19652969bf0eSJack F Vogel 		/*
19662969bf0eSJack F Vogel 		 * Read the 10g AN autoc and LP ability registers and resolve
19672969bf0eSJack F Vogel 		 * local flow control settings accordingly
19682969bf0eSJack F Vogel 		 */
19692969bf0eSJack F Vogel 		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
19702969bf0eSJack F Vogel 		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
19712969bf0eSJack F Vogel 
19722969bf0eSJack F Vogel 		if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
19732969bf0eSJack F Vogel 		    (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) {
19742969bf0eSJack F Vogel 			/*
19752969bf0eSJack F Vogel 			 * Now we need to check if the user selected Rx ONLY
19762969bf0eSJack F Vogel 			 * of pause frames.  In this case, we had to advertise
19772969bf0eSJack F Vogel 			 * FULL flow control because we could not advertise RX
19782969bf0eSJack F Vogel 			 * ONLY. Hence, we must now check to see if we need to
19792969bf0eSJack F Vogel 			 * turn OFF the TRANSMISSION of PAUSE frames.
19802969bf0eSJack F Vogel 			 */
19812969bf0eSJack F Vogel 			if (hw->fc.requested_mode == ixgbe_fc_full) {
19822969bf0eSJack F Vogel 				hw->fc.current_mode = ixgbe_fc_full;
19832969bf0eSJack F Vogel 				DEBUGOUT("Flow Control = FULL.\n");
19842969bf0eSJack F Vogel 			} else {
19852969bf0eSJack F Vogel 				hw->fc.current_mode = ixgbe_fc_rx_pause;
19862969bf0eSJack F Vogel 				DEBUGOUT("Flow Control=RX PAUSE frames only\n");
19872969bf0eSJack F Vogel 			}
19882969bf0eSJack F Vogel 		} else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
19892969bf0eSJack F Vogel 			   (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
19902969bf0eSJack F Vogel 			   (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
19912969bf0eSJack F Vogel 			   (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
19922969bf0eSJack F Vogel 			hw->fc.current_mode = ixgbe_fc_tx_pause;
19932969bf0eSJack F Vogel 			DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
19942969bf0eSJack F Vogel 		} else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
19952969bf0eSJack F Vogel 			   (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
19962969bf0eSJack F Vogel 			   !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
19972969bf0eSJack F Vogel 			   (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
19982969bf0eSJack F Vogel 			hw->fc.current_mode = ixgbe_fc_rx_pause;
19992969bf0eSJack F Vogel 			DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
20002969bf0eSJack F Vogel 		} else {
20012969bf0eSJack F Vogel 			hw->fc.current_mode = ixgbe_fc_none;
20022969bf0eSJack F Vogel 			DEBUGOUT("Flow Control = NONE.\n");
20032969bf0eSJack F Vogel 		}
20042969bf0eSJack F Vogel 	}
20050ac6dfecSJack F Vogel 	/* Record that current_mode is the result of a successful autoneg */
20060ac6dfecSJack F Vogel 	hw->fc.fc_was_autonegged = TRUE;
20070ac6dfecSJack F Vogel 
20081b6e0dbaSJack F Vogel out:
20091b6e0dbaSJack F Vogel 	return ret_val;
20101b6e0dbaSJack F Vogel }
20111b6e0dbaSJack F Vogel 
20120ac6dfecSJack F Vogel /**
20130ac6dfecSJack F Vogel  *  ixgbe_setup_fc - Set up flow control
20140ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
20150ac6dfecSJack F Vogel  *
20160ac6dfecSJack F Vogel  *  Called at init time to set up flow control.
20170ac6dfecSJack F Vogel  **/
20180ac6dfecSJack F Vogel s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
20190ac6dfecSJack F Vogel {
20200ac6dfecSJack F Vogel 	s32 ret_val = IXGBE_SUCCESS;
20210ac6dfecSJack F Vogel 	u32 reg;
20220ac6dfecSJack F Vogel 
20232969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_setup_fc");
20242969bf0eSJack F Vogel 
20250ac6dfecSJack F Vogel 
20260ac6dfecSJack F Vogel 	/* Validate the packetbuf configuration */
20270ac6dfecSJack F Vogel 	if (packetbuf_num < 0 || packetbuf_num > 7) {
20280ac6dfecSJack F Vogel 		DEBUGOUT1("Invalid packet buffer number [%d], expected range is"
20290ac6dfecSJack F Vogel 		          " 0-7\n", packetbuf_num);
20300ac6dfecSJack F Vogel 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
20310ac6dfecSJack F Vogel 		goto out;
20320ac6dfecSJack F Vogel 	}
20330ac6dfecSJack F Vogel 
20340ac6dfecSJack F Vogel 	/*
20350ac6dfecSJack F Vogel 	 * Validate the water mark configuration.  Zero water marks are invalid
20360ac6dfecSJack F Vogel 	 * because it causes the controller to just blast out fc packets.
20370ac6dfecSJack F Vogel 	 */
20380ac6dfecSJack F Vogel 	if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
20390ac6dfecSJack F Vogel 		DEBUGOUT("Invalid water mark configuration\n");
20400ac6dfecSJack F Vogel 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
20410ac6dfecSJack F Vogel 		goto out;
20420ac6dfecSJack F Vogel 	}
20430ac6dfecSJack F Vogel 
20440ac6dfecSJack F Vogel 	/*
20450ac6dfecSJack F Vogel 	 * Validate the requested mode.  Strict IEEE mode does not allow
20460ac6dfecSJack F Vogel 	 * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
20470ac6dfecSJack F Vogel 	 */
20480ac6dfecSJack F Vogel 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
20490ac6dfecSJack F Vogel 		DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
20500ac6dfecSJack F Vogel 		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
20510ac6dfecSJack F Vogel 		goto out;
20520ac6dfecSJack F Vogel 	}
20530ac6dfecSJack F Vogel 
20540ac6dfecSJack F Vogel 	/*
20550ac6dfecSJack F Vogel 	 * 10gig parts do not have a word in the EEPROM to determine the
20560ac6dfecSJack F Vogel 	 * default flow control setting, so we explicitly set it to full.
20570ac6dfecSJack F Vogel 	 */
20580ac6dfecSJack F Vogel 	if (hw->fc.requested_mode == ixgbe_fc_default)
20590ac6dfecSJack F Vogel 		hw->fc.requested_mode = ixgbe_fc_full;
20600ac6dfecSJack F Vogel 
20610ac6dfecSJack F Vogel 	/*
20620ac6dfecSJack F Vogel 	 * Set up the 1G flow control advertisement registers so the HW will be
20630ac6dfecSJack F Vogel 	 * able to do fc autoneg once the cable is plugged in.  If we end up
20640ac6dfecSJack F Vogel 	 * using 10g instead, this is harmless.
20650ac6dfecSJack F Vogel 	 */
20660ac6dfecSJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
20670ac6dfecSJack F Vogel 
20680ac6dfecSJack F Vogel 	/*
20690ac6dfecSJack F Vogel 	 * The possible values of fc.requested_mode are:
20700ac6dfecSJack F Vogel 	 * 0: Flow control is completely disabled
20710ac6dfecSJack F Vogel 	 * 1: Rx flow control is enabled (we can receive pause frames,
20720ac6dfecSJack F Vogel 	 *    but not send pause frames).
20730ac6dfecSJack F Vogel 	 * 2: Tx flow control is enabled (we can send pause frames but
20740ac6dfecSJack F Vogel 	 *    we do not support receiving pause frames).
20750ac6dfecSJack F Vogel 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
20760ac6dfecSJack F Vogel 	 * other: Invalid.
20770ac6dfecSJack F Vogel 	 */
20780ac6dfecSJack F Vogel 	switch (hw->fc.requested_mode) {
20790ac6dfecSJack F Vogel 	case ixgbe_fc_none:
20800ac6dfecSJack F Vogel 		/* Flow control completely disabled by software override. */
20810ac6dfecSJack F Vogel 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
20820ac6dfecSJack F Vogel 		break;
20830ac6dfecSJack F Vogel 	case ixgbe_fc_rx_pause:
20840ac6dfecSJack F Vogel 		/*
20850ac6dfecSJack F Vogel 		 * Rx Flow control is enabled and Tx Flow control is
20860ac6dfecSJack F Vogel 		 * disabled by software override. Since there really
20870ac6dfecSJack F Vogel 		 * isn't a way to advertise that we are capable of RX
20880ac6dfecSJack F Vogel 		 * Pause ONLY, we will advertise that we support both
20890ac6dfecSJack F Vogel 		 * symmetric and asymmetric Rx PAUSE.  Later, we will
20900ac6dfecSJack F Vogel 		 * disable the adapter's ability to send PAUSE frames.
20910ac6dfecSJack F Vogel 		 */
20920ac6dfecSJack F Vogel 		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
20930ac6dfecSJack F Vogel 		break;
20940ac6dfecSJack F Vogel 	case ixgbe_fc_tx_pause:
20950ac6dfecSJack F Vogel 		/*
20960ac6dfecSJack F Vogel 		 * Tx Flow control is enabled, and Rx Flow control is
20970ac6dfecSJack F Vogel 		 * disabled by software override.
20980ac6dfecSJack F Vogel 		 */
20990ac6dfecSJack F Vogel 		reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
21000ac6dfecSJack F Vogel 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
21010ac6dfecSJack F Vogel 		break;
21020ac6dfecSJack F Vogel 	case ixgbe_fc_full:
21030ac6dfecSJack F Vogel 		/* Flow control (both Rx and Tx) is enabled by SW override. */
21040ac6dfecSJack F Vogel 		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
21050ac6dfecSJack F Vogel 		break;
21060ac6dfecSJack F Vogel 	default:
21070ac6dfecSJack F Vogel 		DEBUGOUT("Flow control param set incorrectly\n");
21082969bf0eSJack F Vogel 		ret_val = IXGBE_ERR_CONFIG;
21090ac6dfecSJack F Vogel 		goto out;
21100ac6dfecSJack F Vogel 		break;
21110ac6dfecSJack F Vogel 	}
21120ac6dfecSJack F Vogel 
21130ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
21140ac6dfecSJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
21150ac6dfecSJack F Vogel 
21160ac6dfecSJack F Vogel 	/* Disable AN timeout */
21170ac6dfecSJack F Vogel 	if (hw->fc.strict_ieee)
21180ac6dfecSJack F Vogel 		reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
21190ac6dfecSJack F Vogel 
21200ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
21210ac6dfecSJack F Vogel 	DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
21220ac6dfecSJack F Vogel 
21232969bf0eSJack F Vogel 	/*
21242969bf0eSJack F Vogel 	 * Set up the 10G flow control advertisement registers so the HW
21252969bf0eSJack F Vogel 	 * can do fc autoneg once the cable is plugged in.  If we end up
21262969bf0eSJack F Vogel 	 * using 1g instead, this is harmless.
21272969bf0eSJack F Vogel 	 */
21282969bf0eSJack F Vogel 	reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
21292969bf0eSJack F Vogel 
21302969bf0eSJack F Vogel 	/*
21312969bf0eSJack F Vogel 	 * The possible values of fc.requested_mode are:
21322969bf0eSJack F Vogel 	 * 0: Flow control is completely disabled
21332969bf0eSJack F Vogel 	 * 1: Rx flow control is enabled (we can receive pause frames,
21342969bf0eSJack F Vogel 	 *    but not send pause frames).
21352969bf0eSJack F Vogel 	 * 2: Tx flow control is enabled (we can send pause frames but
21362969bf0eSJack F Vogel 	 *    we do not support receiving pause frames).
21372969bf0eSJack F Vogel 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
21382969bf0eSJack F Vogel 	 * other: Invalid.
21392969bf0eSJack F Vogel 	 */
21402969bf0eSJack F Vogel 	switch (hw->fc.requested_mode) {
21412969bf0eSJack F Vogel 	case ixgbe_fc_none:
21422969bf0eSJack F Vogel 		/* Flow control completely disabled by software override. */
21432969bf0eSJack F Vogel 		reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
21442969bf0eSJack F Vogel 		break;
21452969bf0eSJack F Vogel 	case ixgbe_fc_rx_pause:
21462969bf0eSJack F Vogel 		/*
21472969bf0eSJack F Vogel 		 * Rx Flow control is enabled and Tx Flow control is
21482969bf0eSJack F Vogel 		 * disabled by software override. Since there really
21492969bf0eSJack F Vogel 		 * isn't a way to advertise that we are capable of RX
21502969bf0eSJack F Vogel 		 * Pause ONLY, we will advertise that we support both
21512969bf0eSJack F Vogel 		 * symmetric and asymmetric Rx PAUSE.  Later, we will
21522969bf0eSJack F Vogel 		 * disable the adapter's ability to send PAUSE frames.
21532969bf0eSJack F Vogel 		 */
21542969bf0eSJack F Vogel 		reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
21552969bf0eSJack F Vogel 		break;
21562969bf0eSJack F Vogel 	case ixgbe_fc_tx_pause:
21572969bf0eSJack F Vogel 		/*
21582969bf0eSJack F Vogel 		 * Tx Flow control is enabled, and Rx Flow control is
21592969bf0eSJack F Vogel 		 * disabled by software override.
21602969bf0eSJack F Vogel 		 */
21612969bf0eSJack F Vogel 		reg |= (IXGBE_AUTOC_ASM_PAUSE);
21622969bf0eSJack F Vogel 		reg &= ~(IXGBE_AUTOC_SYM_PAUSE);
21632969bf0eSJack F Vogel 		break;
21642969bf0eSJack F Vogel 	case ixgbe_fc_full:
21652969bf0eSJack F Vogel 		/* Flow control (both Rx and Tx) is enabled by SW override. */
21662969bf0eSJack F Vogel 		reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
21672969bf0eSJack F Vogel 		break;
21682969bf0eSJack F Vogel 	default:
21692969bf0eSJack F Vogel 		DEBUGOUT("Flow control param set incorrectly\n");
21702969bf0eSJack F Vogel 		ret_val = IXGBE_ERR_CONFIG;
21712969bf0eSJack F Vogel 		goto out;
21722969bf0eSJack F Vogel 		break;
21732969bf0eSJack F Vogel 	}
21742969bf0eSJack F Vogel 	/*
21752969bf0eSJack F Vogel 	 * AUTOC restart handles negotiation of 1G and 10G. There is
21762969bf0eSJack F Vogel 	 * no need to set the PCS1GCTL register.
21772969bf0eSJack F Vogel 	 */
21782969bf0eSJack F Vogel 	reg |= IXGBE_AUTOC_AN_RESTART;
21792969bf0eSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg);
21802969bf0eSJack F Vogel 	DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
21812969bf0eSJack F Vogel 
21820ac6dfecSJack F Vogel out:
21830ac6dfecSJack F Vogel 	return ret_val;
21840ac6dfecSJack F Vogel }
21851b6e0dbaSJack F Vogel 
218613705f88SJack F Vogel /**
218713705f88SJack F Vogel  *  ixgbe_disable_pcie_master - Disable PCI-express master access
218813705f88SJack F Vogel  *  @hw: pointer to hardware structure
218913705f88SJack F Vogel  *
219013705f88SJack F Vogel  *  Disables PCI-Express master access and verifies there are no pending
219113705f88SJack F Vogel  *  requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
219213705f88SJack F Vogel  *  bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS
219313705f88SJack F Vogel  *  is returned signifying master requests disabled.
219413705f88SJack F Vogel  **/
219513705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
219613705f88SJack F Vogel {
21975b7f4cedSJack F Vogel 	u32 i;
21985b7f4cedSJack F Vogel 	u32 reg_val;
21995b7f4cedSJack F Vogel 	u32 number_of_queues;
2200c0014855SJack F Vogel 	s32 status = IXGBE_SUCCESS;
220113705f88SJack F Vogel 
22022969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_disable_pcie_master");
22032969bf0eSJack F Vogel 
2204c0014855SJack F Vogel 	/* Just jump out if bus mastering is already disabled */
2205c0014855SJack F Vogel 	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
2206c0014855SJack F Vogel 		goto out;
2207c0014855SJack F Vogel 
22085b7f4cedSJack F Vogel 	/* Disable the receive unit by stopping each queue */
22095b7f4cedSJack F Vogel 	number_of_queues = hw->mac.max_rx_queues;
22105b7f4cedSJack F Vogel 	for (i = 0; i < number_of_queues; i++) {
22115b7f4cedSJack F Vogel 		reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
22125b7f4cedSJack F Vogel 		if (reg_val & IXGBE_RXDCTL_ENABLE) {
22135b7f4cedSJack F Vogel 			reg_val &= ~IXGBE_RXDCTL_ENABLE;
22145b7f4cedSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
22155b7f4cedSJack F Vogel 		}
22165b7f4cedSJack F Vogel 	}
22175b7f4cedSJack F Vogel 
22185b7f4cedSJack F Vogel 	reg_val = IXGBE_READ_REG(hw, IXGBE_CTRL);
22195b7f4cedSJack F Vogel 	reg_val |= IXGBE_CTRL_GIO_DIS;
22205b7f4cedSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val);
222113705f88SJack F Vogel 
222213705f88SJack F Vogel 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
2223c0014855SJack F Vogel 		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
2224c0014855SJack F Vogel 			goto out;
222513705f88SJack F Vogel 		usec_delay(100);
222613705f88SJack F Vogel 	}
222713705f88SJack F Vogel 
2228c0014855SJack F Vogel 	DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
2229c0014855SJack F Vogel 	status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
2230c0014855SJack F Vogel 
2231c0014855SJack F Vogel 	/*
2232c0014855SJack F Vogel 	 * The GIO Master Disable bit didn't clear.  There are multiple reasons
2233c0014855SJack F Vogel 	 * for this listed in the datasheet 5.2.5.3.2 Master Disable, and they
2234c0014855SJack F Vogel 	 * all require a double reset to recover from.  Before proceeding, we
2235c0014855SJack F Vogel 	 * first wait a little more to try to ensure that, at a minimum, the
2236c0014855SJack F Vogel 	 * PCIe block has no transactions pending.
2237c0014855SJack F Vogel 	 */
2238c0014855SJack F Vogel 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
2239c0014855SJack F Vogel 		if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) &
2240c0014855SJack F Vogel 			IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
2241c0014855SJack F Vogel 			break;
2242c0014855SJack F Vogel 		usec_delay(100);
2243c0014855SJack F Vogel 	}
2244c0014855SJack F Vogel 
2245c0014855SJack F Vogel 	if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT)
2246c0014855SJack F Vogel 		DEBUGOUT("PCIe transaction pending bit also did not clear.\n");
2247c0014855SJack F Vogel 
2248c0014855SJack F Vogel 	/*
2249c0014855SJack F Vogel 	 * Two consecutive resets are required via CTRL.RST per datasheet
2250c0014855SJack F Vogel 	 * 5.2.5.3.2 Master Disable.  We set a flag to inform the reset routine
2251c0014855SJack F Vogel 	 * of this need.  The first reset prevents new master requests from
2252c0014855SJack F Vogel 	 * being issued by our device.  We then must wait 1usec for any
2253c0014855SJack F Vogel 	 * remaining completions from the PCIe bus to trickle in, and then reset
2254c0014855SJack F Vogel 	 * again to clear out any effects they may have had on our device.
2255c0014855SJack F Vogel 	 */
2256c0014855SJack F Vogel 	 hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
2257c0014855SJack F Vogel 
2258c0014855SJack F Vogel out:
225913705f88SJack F Vogel 	return status;
226013705f88SJack F Vogel }
226113705f88SJack F Vogel 
226213705f88SJack F Vogel 
226313705f88SJack F Vogel /**
22649ca4041bSJack F Vogel  *  ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
226513705f88SJack F Vogel  *  @hw: pointer to hardware structure
22669ca4041bSJack F Vogel  *  @mask: Mask to specify which semaphore to acquire
226713705f88SJack F Vogel  *
22689ca4041bSJack F Vogel  *  Acquires the SWFW semaphore thought the GSSR register for the specified
226913705f88SJack F Vogel  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
227013705f88SJack F Vogel  **/
227113705f88SJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
227213705f88SJack F Vogel {
227313705f88SJack F Vogel 	u32 gssr;
227413705f88SJack F Vogel 	u32 swmask = mask;
227513705f88SJack F Vogel 	u32 fwmask = mask << 5;
227613705f88SJack F Vogel 	s32 timeout = 200;
227713705f88SJack F Vogel 
22782969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_acquire_swfw_sync");
22792969bf0eSJack F Vogel 
228013705f88SJack F Vogel 	while (timeout) {
22810ac6dfecSJack F Vogel 		/*
22820ac6dfecSJack F Vogel 		 * SW EEPROM semaphore bit is used for access to all
22830ac6dfecSJack F Vogel 		 * SW_FW_SYNC/GSSR bits (not just EEPROM)
22840ac6dfecSJack F Vogel 		 */
228513705f88SJack F Vogel 		if (ixgbe_get_eeprom_semaphore(hw))
22862969bf0eSJack F Vogel 			return IXGBE_ERR_SWFW_SYNC;
228713705f88SJack F Vogel 
228813705f88SJack F Vogel 		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
228913705f88SJack F Vogel 		if (!(gssr & (fwmask | swmask)))
229013705f88SJack F Vogel 			break;
229113705f88SJack F Vogel 
229213705f88SJack F Vogel 		/*
229313705f88SJack F Vogel 		 * Firmware currently using resource (fwmask) or other software
229413705f88SJack F Vogel 		 * thread currently using resource (swmask)
229513705f88SJack F Vogel 		 */
229613705f88SJack F Vogel 		ixgbe_release_eeprom_semaphore(hw);
229713705f88SJack F Vogel 		msec_delay(5);
229813705f88SJack F Vogel 		timeout--;
229913705f88SJack F Vogel 	}
230013705f88SJack F Vogel 
230113705f88SJack F Vogel 	if (!timeout) {
23020ac6dfecSJack F Vogel 		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
23032969bf0eSJack F Vogel 		return IXGBE_ERR_SWFW_SYNC;
230413705f88SJack F Vogel 	}
230513705f88SJack F Vogel 
230613705f88SJack F Vogel 	gssr |= swmask;
230713705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
230813705f88SJack F Vogel 
230913705f88SJack F Vogel 	ixgbe_release_eeprom_semaphore(hw);
231013705f88SJack F Vogel 	return IXGBE_SUCCESS;
231113705f88SJack F Vogel }
231213705f88SJack F Vogel 
231313705f88SJack F Vogel /**
231413705f88SJack F Vogel  *  ixgbe_release_swfw_sync - Release SWFW semaphore
231513705f88SJack F Vogel  *  @hw: pointer to hardware structure
23169ca4041bSJack F Vogel  *  @mask: Mask to specify which semaphore to release
231713705f88SJack F Vogel  *
23189ca4041bSJack F Vogel  *  Releases the SWFW semaphore thought the GSSR register for the specified
231913705f88SJack F Vogel  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
232013705f88SJack F Vogel  **/
232113705f88SJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
232213705f88SJack F Vogel {
232313705f88SJack F Vogel 	u32 gssr;
232413705f88SJack F Vogel 	u32 swmask = mask;
232513705f88SJack F Vogel 
23262969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_release_swfw_sync");
23272969bf0eSJack F Vogel 
232813705f88SJack F Vogel 	ixgbe_get_eeprom_semaphore(hw);
232913705f88SJack F Vogel 
233013705f88SJack F Vogel 	gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
233113705f88SJack F Vogel 	gssr &= ~swmask;
233213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
233313705f88SJack F Vogel 
233413705f88SJack F Vogel 	ixgbe_release_eeprom_semaphore(hw);
23350ac6dfecSJack F Vogel }
23360ac6dfecSJack F Vogel 
23370ac6dfecSJack F Vogel /**
23380ac6dfecSJack F Vogel  *  ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
23390ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
23400ac6dfecSJack F Vogel  *  @regval: register value to write to RXCTRL
23410ac6dfecSJack F Vogel  *
23420ac6dfecSJack F Vogel  *  Enables the Rx DMA unit
23430ac6dfecSJack F Vogel  **/
23440ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval)
23450ac6dfecSJack F Vogel {
23462969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_enable_rx_dma_generic");
23472969bf0eSJack F Vogel 
23480ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
23490ac6dfecSJack F Vogel 
23500ac6dfecSJack F Vogel 	return IXGBE_SUCCESS;
23510ac6dfecSJack F Vogel }
23520ac6dfecSJack F Vogel 
23530ac6dfecSJack F Vogel /**
23540ac6dfecSJack F Vogel  *  ixgbe_blink_led_start_generic - Blink LED based on index.
23550ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
23560ac6dfecSJack F Vogel  *  @index: led number to blink
23570ac6dfecSJack F Vogel  **/
23580ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
23590ac6dfecSJack F Vogel {
23600ac6dfecSJack F Vogel 	ixgbe_link_speed speed = 0;
23610ac6dfecSJack F Vogel 	bool link_up = 0;
23620ac6dfecSJack F Vogel 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
23630ac6dfecSJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
23640ac6dfecSJack F Vogel 
23652969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_blink_led_start_generic");
23662969bf0eSJack F Vogel 
23670ac6dfecSJack F Vogel 	/*
23680ac6dfecSJack F Vogel 	 * Link must be up to auto-blink the LEDs;
23690ac6dfecSJack F Vogel 	 * Force it if link is down.
23700ac6dfecSJack F Vogel 	 */
23710ac6dfecSJack F Vogel 	hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
23720ac6dfecSJack F Vogel 
23730ac6dfecSJack F Vogel 	if (!link_up) {
2374d8602bb9SJack F Vogel 
2375d8602bb9SJack F Vogel 		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
23760ac6dfecSJack F Vogel 		autoc_reg |= IXGBE_AUTOC_FLU;
23770ac6dfecSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
23780ac6dfecSJack F Vogel 		msec_delay(10);
23790ac6dfecSJack F Vogel 	}
23800ac6dfecSJack F Vogel 
23810ac6dfecSJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
23820ac6dfecSJack F Vogel 	led_reg |= IXGBE_LED_BLINK(index);
23830ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
23840ac6dfecSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
23850ac6dfecSJack F Vogel 
23860ac6dfecSJack F Vogel 	return IXGBE_SUCCESS;
23870ac6dfecSJack F Vogel }
23880ac6dfecSJack F Vogel 
23890ac6dfecSJack F Vogel /**
23900ac6dfecSJack F Vogel  *  ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
23910ac6dfecSJack F Vogel  *  @hw: pointer to hardware structure
23920ac6dfecSJack F Vogel  *  @index: led number to stop blinking
23930ac6dfecSJack F Vogel  **/
23940ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
23950ac6dfecSJack F Vogel {
23960ac6dfecSJack F Vogel 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
23970ac6dfecSJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
23980ac6dfecSJack F Vogel 
23992969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_blink_led_stop_generic");
24002969bf0eSJack F Vogel 
2401d8602bb9SJack F Vogel 
24020ac6dfecSJack F Vogel 	autoc_reg &= ~IXGBE_AUTOC_FLU;
24030ac6dfecSJack F Vogel 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
24040ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
24050ac6dfecSJack F Vogel 
24060ac6dfecSJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
24070ac6dfecSJack F Vogel 	led_reg &= ~IXGBE_LED_BLINK(index);
24080ac6dfecSJack F Vogel 	led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
24090ac6dfecSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
24100ac6dfecSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
24110ac6dfecSJack F Vogel 
24120ac6dfecSJack F Vogel 	return IXGBE_SUCCESS;
241313705f88SJack F Vogel }
241413705f88SJack F Vogel 
24152969bf0eSJack F Vogel /**
24162969bf0eSJack F Vogel  *  ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
24172969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
24182969bf0eSJack F Vogel  *  @san_mac_offset: SAN MAC address offset
24192969bf0eSJack F Vogel  *
24202969bf0eSJack F Vogel  *  This function will read the EEPROM location for the SAN MAC address
24212969bf0eSJack F Vogel  *  pointer, and returns the value at that location.  This is used in both
24222969bf0eSJack F Vogel  *  get and set mac_addr routines.
24232969bf0eSJack F Vogel  **/
24242969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
24252969bf0eSJack F Vogel                                         u16 *san_mac_offset)
24262969bf0eSJack F Vogel {
24272969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_san_mac_addr_offset");
24282969bf0eSJack F Vogel 
24292969bf0eSJack F Vogel 	/*
24302969bf0eSJack F Vogel 	 * First read the EEPROM pointer to see if the MAC addresses are
24312969bf0eSJack F Vogel 	 * available.
24322969bf0eSJack F Vogel 	 */
24332969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset);
24342969bf0eSJack F Vogel 
24352969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
24362969bf0eSJack F Vogel }
24372969bf0eSJack F Vogel 
24382969bf0eSJack F Vogel /**
24392969bf0eSJack F Vogel  *  ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM
24402969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
24412969bf0eSJack F Vogel  *  @san_mac_addr: SAN MAC address
24422969bf0eSJack F Vogel  *
24432969bf0eSJack F Vogel  *  Reads the SAN MAC address from the EEPROM, if it's available.  This is
24442969bf0eSJack F Vogel  *  per-port, so set_lan_id() must be called before reading the addresses.
24452969bf0eSJack F Vogel  *  set_lan_id() is called by identify_sfp(), but this cannot be relied
24462969bf0eSJack F Vogel  *  upon for non-SFP connections, so we must call it here.
24472969bf0eSJack F Vogel  **/
24482969bf0eSJack F Vogel s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
24492969bf0eSJack F Vogel {
24502969bf0eSJack F Vogel 	u16 san_mac_data, san_mac_offset;
24512969bf0eSJack F Vogel 	u8 i;
24522969bf0eSJack F Vogel 
24532969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_san_mac_addr_generic");
24542969bf0eSJack F Vogel 
24552969bf0eSJack F Vogel 	/*
24562969bf0eSJack F Vogel 	 * First read the EEPROM pointer to see if the MAC addresses are
24572969bf0eSJack F Vogel 	 * available.  If they're not, no point in calling set_lan_id() here.
24582969bf0eSJack F Vogel 	 */
24592969bf0eSJack F Vogel 	ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
24602969bf0eSJack F Vogel 
24612969bf0eSJack F Vogel 	if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
24622969bf0eSJack F Vogel 		/*
24632969bf0eSJack F Vogel 		 * No addresses available in this EEPROM.  It's not an
24642969bf0eSJack F Vogel 		 * error though, so just wipe the local address and return.
24652969bf0eSJack F Vogel 		 */
24662969bf0eSJack F Vogel 		for (i = 0; i < 6; i++)
24672969bf0eSJack F Vogel 			san_mac_addr[i] = 0xFF;
24682969bf0eSJack F Vogel 
24692969bf0eSJack F Vogel 		goto san_mac_addr_out;
24702969bf0eSJack F Vogel 	}
24712969bf0eSJack F Vogel 
24722969bf0eSJack F Vogel 	/* make sure we know which port we need to program */
24732969bf0eSJack F Vogel 	hw->mac.ops.set_lan_id(hw);
24742969bf0eSJack F Vogel 	/* apply the port offset to the address offset */
24752969bf0eSJack F Vogel 	(hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
24762969bf0eSJack F Vogel 	                 (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
24772969bf0eSJack F Vogel 	for (i = 0; i < 3; i++) {
24782969bf0eSJack F Vogel 		hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data);
24792969bf0eSJack F Vogel 		san_mac_addr[i * 2] = (u8)(san_mac_data);
24802969bf0eSJack F Vogel 		san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
24812969bf0eSJack F Vogel 		san_mac_offset++;
24822969bf0eSJack F Vogel 	}
24832969bf0eSJack F Vogel 
24842969bf0eSJack F Vogel san_mac_addr_out:
24852969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
24862969bf0eSJack F Vogel }
24872969bf0eSJack F Vogel 
24882969bf0eSJack F Vogel /**
24892969bf0eSJack F Vogel  *  ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM
24902969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
24912969bf0eSJack F Vogel  *  @san_mac_addr: SAN MAC address
24922969bf0eSJack F Vogel  *
24932969bf0eSJack F Vogel  *  Write a SAN MAC address to the EEPROM.
24942969bf0eSJack F Vogel  **/
24952969bf0eSJack F Vogel s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
24962969bf0eSJack F Vogel {
24972969bf0eSJack F Vogel 	s32 status = IXGBE_SUCCESS;
24982969bf0eSJack F Vogel 	u16 san_mac_data, san_mac_offset;
24992969bf0eSJack F Vogel 	u8 i;
25002969bf0eSJack F Vogel 
25012969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_san_mac_addr_generic");
25022969bf0eSJack F Vogel 
25032969bf0eSJack F Vogel 	/* Look for SAN mac address pointer.  If not defined, return */
25042969bf0eSJack F Vogel 	ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
25052969bf0eSJack F Vogel 
25062969bf0eSJack F Vogel 	if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
25072969bf0eSJack F Vogel 		status = IXGBE_ERR_NO_SAN_ADDR_PTR;
25082969bf0eSJack F Vogel 		goto san_mac_addr_out;
25092969bf0eSJack F Vogel 	}
25102969bf0eSJack F Vogel 
25112969bf0eSJack F Vogel 	/* Make sure we know which port we need to write */
25122969bf0eSJack F Vogel 	hw->mac.ops.set_lan_id(hw);
25132969bf0eSJack F Vogel 	/* Apply the port offset to the address offset */
25142969bf0eSJack F Vogel 	(hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
25152969bf0eSJack F Vogel 	                 (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
25162969bf0eSJack F Vogel 
25172969bf0eSJack F Vogel 	for (i = 0; i < 3; i++) {
25182969bf0eSJack F Vogel 		san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8);
25192969bf0eSJack F Vogel 		san_mac_data |= (u16)(san_mac_addr[i * 2]);
25202969bf0eSJack F Vogel 		hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data);
25212969bf0eSJack F Vogel 		san_mac_offset++;
25222969bf0eSJack F Vogel 	}
25232969bf0eSJack F Vogel 
25242969bf0eSJack F Vogel san_mac_addr_out:
25252969bf0eSJack F Vogel 	return status;
25262969bf0eSJack F Vogel }
25272969bf0eSJack F Vogel 
25282969bf0eSJack F Vogel /**
25292969bf0eSJack F Vogel  *  ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count
25302969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
25312969bf0eSJack F Vogel  *
25322969bf0eSJack F Vogel  *  Read PCIe configuration space, and get the MSI-X vector count from
25332969bf0eSJack F Vogel  *  the capabilities table.
25342969bf0eSJack F Vogel  **/
25352969bf0eSJack F Vogel u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
25362969bf0eSJack F Vogel {
25372969bf0eSJack F Vogel 	u32 msix_count = 64;
25382969bf0eSJack F Vogel 
25392969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_pcie_msix_count_generic");
25402969bf0eSJack F Vogel 	if (hw->mac.msix_vectors_from_pcie) {
25412969bf0eSJack F Vogel 		msix_count = IXGBE_READ_PCIE_WORD(hw,
25422969bf0eSJack F Vogel 		                                  IXGBE_PCIE_MSIX_82599_CAPS);
25432969bf0eSJack F Vogel 		msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
25442969bf0eSJack F Vogel 
25452969bf0eSJack F Vogel 		/* MSI-X count is zero-based in HW, so increment to give
25462969bf0eSJack F Vogel 		 * proper value */
25472969bf0eSJack F Vogel 		msix_count++;
25482969bf0eSJack F Vogel 	}
25492969bf0eSJack F Vogel 
25502969bf0eSJack F Vogel 	return msix_count;
25512969bf0eSJack F Vogel }
25522969bf0eSJack F Vogel 
25532969bf0eSJack F Vogel /**
25542969bf0eSJack F Vogel  *  ixgbe_insert_mac_addr_generic - Find a RAR for this mac address
25552969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
25562969bf0eSJack F Vogel  *  @addr: Address to put into receive address register
25572969bf0eSJack F Vogel  *  @vmdq: VMDq pool to assign
25582969bf0eSJack F Vogel  *
25592969bf0eSJack F Vogel  *  Puts an ethernet address into a receive address register, or
25602969bf0eSJack F Vogel  *  finds the rar that it is aleady in; adds to the pool list
25612969bf0eSJack F Vogel  **/
25622969bf0eSJack F Vogel s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
25632969bf0eSJack F Vogel {
25642969bf0eSJack F Vogel 	static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF;
25652969bf0eSJack F Vogel 	u32 first_empty_rar = NO_EMPTY_RAR_FOUND;
25662969bf0eSJack F Vogel 	u32 rar;
25672969bf0eSJack F Vogel 	u32 rar_low, rar_high;
25682969bf0eSJack F Vogel 	u32 addr_low, addr_high;
25692969bf0eSJack F Vogel 
25702969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_insert_mac_addr_generic");
25712969bf0eSJack F Vogel 
25722969bf0eSJack F Vogel 	/* swap bytes for HW little endian */
25732969bf0eSJack F Vogel 	addr_low  = addr[0] | (addr[1] << 8)
25742969bf0eSJack F Vogel 			    | (addr[2] << 16)
25752969bf0eSJack F Vogel 			    | (addr[3] << 24);
25762969bf0eSJack F Vogel 	addr_high = addr[4] | (addr[5] << 8);
25772969bf0eSJack F Vogel 
25782969bf0eSJack F Vogel 	/*
25792969bf0eSJack F Vogel 	 * Either find the mac_id in rar or find the first empty space.
25802969bf0eSJack F Vogel 	 * rar_highwater points to just after the highest currently used
25812969bf0eSJack F Vogel 	 * rar in order to shorten the search.  It grows when we add a new
25822969bf0eSJack F Vogel 	 * rar to the top.
25832969bf0eSJack F Vogel 	 */
25842969bf0eSJack F Vogel 	for (rar = 0; rar < hw->mac.rar_highwater; rar++) {
25852969bf0eSJack F Vogel 		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
25862969bf0eSJack F Vogel 
25872969bf0eSJack F Vogel 		if (((IXGBE_RAH_AV & rar_high) == 0)
25882969bf0eSJack F Vogel 		    && first_empty_rar == NO_EMPTY_RAR_FOUND) {
25892969bf0eSJack F Vogel 			first_empty_rar = rar;
25902969bf0eSJack F Vogel 		} else if ((rar_high & 0xFFFF) == addr_high) {
25912969bf0eSJack F Vogel 			rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar));
25922969bf0eSJack F Vogel 			if (rar_low == addr_low)
25932969bf0eSJack F Vogel 				break;    /* found it already in the rars */
25942969bf0eSJack F Vogel 		}
25952969bf0eSJack F Vogel 	}
25962969bf0eSJack F Vogel 
25972969bf0eSJack F Vogel 	if (rar < hw->mac.rar_highwater) {
25982969bf0eSJack F Vogel 		/* already there so just add to the pool bits */
25992969bf0eSJack F Vogel 		ixgbe_set_vmdq(hw, rar, vmdq);
26002969bf0eSJack F Vogel 	} else if (first_empty_rar != NO_EMPTY_RAR_FOUND) {
26012969bf0eSJack F Vogel 		/* stick it into first empty RAR slot we found */
26022969bf0eSJack F Vogel 		rar = first_empty_rar;
26032969bf0eSJack F Vogel 		ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
26042969bf0eSJack F Vogel 	} else if (rar == hw->mac.rar_highwater) {
26052969bf0eSJack F Vogel 		/* add it to the top of the list and inc the highwater mark */
26062969bf0eSJack F Vogel 		ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
26072969bf0eSJack F Vogel 		hw->mac.rar_highwater++;
26082969bf0eSJack F Vogel 	} else if (rar >= hw->mac.num_rar_entries) {
26092969bf0eSJack F Vogel 		return IXGBE_ERR_INVALID_MAC_ADDR;
26102969bf0eSJack F Vogel 	}
26112969bf0eSJack F Vogel 
26122969bf0eSJack F Vogel 	/*
26132969bf0eSJack F Vogel 	 * If we found rar[0], make sure the default pool bit (we use pool 0)
26142969bf0eSJack F Vogel 	 * remains cleared to be sure default pool packets will get delivered
26152969bf0eSJack F Vogel 	 */
26162969bf0eSJack F Vogel 	if (rar == 0)
26172969bf0eSJack F Vogel 		ixgbe_clear_vmdq(hw, rar, 0);
26182969bf0eSJack F Vogel 
26192969bf0eSJack F Vogel 	return rar;
26202969bf0eSJack F Vogel }
26212969bf0eSJack F Vogel 
26222969bf0eSJack F Vogel /**
26232969bf0eSJack F Vogel  *  ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address
26242969bf0eSJack F Vogel  *  @hw: pointer to hardware struct
26252969bf0eSJack F Vogel  *  @rar: receive address register index to disassociate
26262969bf0eSJack F Vogel  *  @vmdq: VMDq pool index to remove from the rar
26272969bf0eSJack F Vogel  **/
26282969bf0eSJack F Vogel s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
26292969bf0eSJack F Vogel {
26302969bf0eSJack F Vogel 	u32 mpsar_lo, mpsar_hi;
26312969bf0eSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
26322969bf0eSJack F Vogel 
26332969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_clear_vmdq_generic");
26342969bf0eSJack F Vogel 
26352969bf0eSJack F Vogel 	if (rar < rar_entries) {
26362969bf0eSJack F Vogel 		mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
26372969bf0eSJack F Vogel 		mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
26382969bf0eSJack F Vogel 
26392969bf0eSJack F Vogel 		if (!mpsar_lo && !mpsar_hi)
26402969bf0eSJack F Vogel 			goto done;
26412969bf0eSJack F Vogel 
26422969bf0eSJack F Vogel 		if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
26432969bf0eSJack F Vogel 			if (mpsar_lo) {
26442969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
26452969bf0eSJack F Vogel 				mpsar_lo = 0;
26462969bf0eSJack F Vogel 			}
26472969bf0eSJack F Vogel 			if (mpsar_hi) {
26482969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
26492969bf0eSJack F Vogel 				mpsar_hi = 0;
26502969bf0eSJack F Vogel 			}
26512969bf0eSJack F Vogel 		} else if (vmdq < 32) {
26522969bf0eSJack F Vogel 			mpsar_lo &= ~(1 << vmdq);
26532969bf0eSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
26542969bf0eSJack F Vogel 		} else {
26552969bf0eSJack F Vogel 			mpsar_hi &= ~(1 << (vmdq - 32));
26562969bf0eSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
26572969bf0eSJack F Vogel 		}
26582969bf0eSJack F Vogel 
26592969bf0eSJack F Vogel 		/* was that the last pool using this rar? */
26602969bf0eSJack F Vogel 		if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
26612969bf0eSJack F Vogel 			hw->mac.ops.clear_rar(hw, rar);
26622969bf0eSJack F Vogel 	} else {
26632969bf0eSJack F Vogel 		DEBUGOUT1("RAR index %d is out of range.\n", rar);
26642969bf0eSJack F Vogel 	}
26652969bf0eSJack F Vogel 
26662969bf0eSJack F Vogel done:
26672969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
26682969bf0eSJack F Vogel }
26692969bf0eSJack F Vogel 
26702969bf0eSJack F Vogel /**
26712969bf0eSJack F Vogel  *  ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address
26722969bf0eSJack F Vogel  *  @hw: pointer to hardware struct
26732969bf0eSJack F Vogel  *  @rar: receive address register index to associate with a VMDq index
26742969bf0eSJack F Vogel  *  @vmdq: VMDq pool index
26752969bf0eSJack F Vogel  **/
26762969bf0eSJack F Vogel s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
26772969bf0eSJack F Vogel {
26782969bf0eSJack F Vogel 	u32 mpsar;
26792969bf0eSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
26802969bf0eSJack F Vogel 
26812969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_vmdq_generic");
26822969bf0eSJack F Vogel 
26832969bf0eSJack F Vogel 	if (rar < rar_entries) {
26842969bf0eSJack F Vogel 		if (vmdq < 32) {
26852969bf0eSJack F Vogel 			mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
26862969bf0eSJack F Vogel 			mpsar |= 1 << vmdq;
26872969bf0eSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
26882969bf0eSJack F Vogel 		} else {
26892969bf0eSJack F Vogel 			mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
26902969bf0eSJack F Vogel 			mpsar |= 1 << (vmdq - 32);
26912969bf0eSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
26922969bf0eSJack F Vogel 		}
26932969bf0eSJack F Vogel 	} else {
26942969bf0eSJack F Vogel 		DEBUGOUT1("RAR index %d is out of range.\n", rar);
26952969bf0eSJack F Vogel 	}
26962969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
26972969bf0eSJack F Vogel }
26982969bf0eSJack F Vogel 
26992969bf0eSJack F Vogel /**
27002969bf0eSJack F Vogel  *  ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array
27012969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
27022969bf0eSJack F Vogel  **/
27032969bf0eSJack F Vogel s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
27042969bf0eSJack F Vogel {
27052969bf0eSJack F Vogel 	int i;
27062969bf0eSJack F Vogel 
27072969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_init_uta_tables_generic");
27082969bf0eSJack F Vogel 	DEBUGOUT(" Clearing UTA\n");
27092969bf0eSJack F Vogel 
27102969bf0eSJack F Vogel 	for (i = 0; i < 128; i++)
27112969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
27122969bf0eSJack F Vogel 
27132969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
27142969bf0eSJack F Vogel }
27152969bf0eSJack F Vogel 
27162969bf0eSJack F Vogel /**
27172969bf0eSJack F Vogel  *  ixgbe_find_vlvf_slot - find the vlanid or the first empty slot
27182969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
27192969bf0eSJack F Vogel  *  @vlan: VLAN id to write to VLAN filter
27202969bf0eSJack F Vogel  *
27212969bf0eSJack F Vogel  *  return the VLVF index where this VLAN id should be placed
27222969bf0eSJack F Vogel  *
27232969bf0eSJack F Vogel  **/
27242969bf0eSJack F Vogel s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
27252969bf0eSJack F Vogel {
27262969bf0eSJack F Vogel 	u32 bits = 0;
27272969bf0eSJack F Vogel 	u32 first_empty_slot = 0;
27282969bf0eSJack F Vogel 	s32 regindex;
27292969bf0eSJack F Vogel 
2730c0014855SJack F Vogel 	/* short cut the special case */
2731c0014855SJack F Vogel 	if (vlan == 0)
2732c0014855SJack F Vogel 		return 0;
2733c0014855SJack F Vogel 
27342969bf0eSJack F Vogel 	/*
27352969bf0eSJack F Vogel 	  * Search for the vlan id in the VLVF entries. Save off the first empty
27362969bf0eSJack F Vogel 	  * slot found along the way
27372969bf0eSJack F Vogel 	  */
27382969bf0eSJack F Vogel 	for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
27392969bf0eSJack F Vogel 		bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
27402969bf0eSJack F Vogel 		if (!bits && !(first_empty_slot))
27412969bf0eSJack F Vogel 			first_empty_slot = regindex;
27422969bf0eSJack F Vogel 		else if ((bits & 0x0FFF) == vlan)
27432969bf0eSJack F Vogel 			break;
27442969bf0eSJack F Vogel 	}
27452969bf0eSJack F Vogel 
27462969bf0eSJack F Vogel 	/*
27472969bf0eSJack F Vogel 	  * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan
27482969bf0eSJack F Vogel 	  * in the VLVF. Else use the first empty VLVF register for this
27492969bf0eSJack F Vogel 	  * vlan id.
27502969bf0eSJack F Vogel 	  */
27512969bf0eSJack F Vogel 	if (regindex >= IXGBE_VLVF_ENTRIES) {
27522969bf0eSJack F Vogel 		if (first_empty_slot)
27532969bf0eSJack F Vogel 			regindex = first_empty_slot;
27542969bf0eSJack F Vogel 		else {
27552969bf0eSJack F Vogel 			DEBUGOUT("No space in VLVF.\n");
2756c0014855SJack F Vogel 			regindex = IXGBE_ERR_NO_SPACE;
27572969bf0eSJack F Vogel 		}
27582969bf0eSJack F Vogel 	}
27592969bf0eSJack F Vogel 
27602969bf0eSJack F Vogel 	return regindex;
27612969bf0eSJack F Vogel }
27622969bf0eSJack F Vogel 
27632969bf0eSJack F Vogel /**
27642969bf0eSJack F Vogel  *  ixgbe_set_vfta_generic - Set VLAN filter table
27652969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
27662969bf0eSJack F Vogel  *  @vlan: VLAN id to write to VLAN filter
27672969bf0eSJack F Vogel  *  @vind: VMDq output index that maps queue to VLAN id in VFVFB
27682969bf0eSJack F Vogel  *  @vlan_on: boolean flag to turn on/off VLAN in VFVF
27692969bf0eSJack F Vogel  *
27702969bf0eSJack F Vogel  *  Turn on/off specified VLAN in the VLAN filter table.
27712969bf0eSJack F Vogel  **/
27722969bf0eSJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
27732969bf0eSJack F Vogel                            bool vlan_on)
27742969bf0eSJack F Vogel {
27752969bf0eSJack F Vogel 	s32 regindex;
27762969bf0eSJack F Vogel 	u32 bitindex;
2777c0014855SJack F Vogel 	u32 vfta;
27782969bf0eSJack F Vogel 	u32 bits;
27792969bf0eSJack F Vogel 	u32 vt;
2780c0014855SJack F Vogel 	u32 targetbit;
2781c0014855SJack F Vogel 	bool vfta_changed = FALSE;
27822969bf0eSJack F Vogel 
27832969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_set_vfta_generic");
27842969bf0eSJack F Vogel 
27852969bf0eSJack F Vogel 	if (vlan > 4095)
27862969bf0eSJack F Vogel 		return IXGBE_ERR_PARAM;
27872969bf0eSJack F Vogel 
27882969bf0eSJack F Vogel 	/*
27892969bf0eSJack F Vogel 	 * this is a 2 part operation - first the VFTA, then the
27902969bf0eSJack F Vogel 	 * VLVF and VLVFB if VT Mode is set
2791c0014855SJack F Vogel 	 * We don't write the VFTA until we know the VLVF part succeeded.
27922969bf0eSJack F Vogel 	 */
27932969bf0eSJack F Vogel 
27942969bf0eSJack F Vogel 	/* Part 1
27952969bf0eSJack F Vogel 	 * The VFTA is a bitstring made up of 128 32-bit registers
27962969bf0eSJack F Vogel 	 * that enable the particular VLAN id, much like the MTA:
27972969bf0eSJack F Vogel 	 *    bits[11-5]: which register
27982969bf0eSJack F Vogel 	 *    bits[4-0]:  which bit in the register
27992969bf0eSJack F Vogel 	 */
28002969bf0eSJack F Vogel 	regindex = (vlan >> 5) & 0x7F;
28012969bf0eSJack F Vogel 	bitindex = vlan & 0x1F;
2802c0014855SJack F Vogel 	targetbit = (1 << bitindex);
2803c0014855SJack F Vogel 	vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
28042969bf0eSJack F Vogel 
2805c0014855SJack F Vogel 	if (vlan_on) {
2806c0014855SJack F Vogel 		if (!(vfta & targetbit)) {
2807c0014855SJack F Vogel 			vfta |= targetbit;
2808c0014855SJack F Vogel 			vfta_changed = TRUE;
2809c0014855SJack F Vogel 		}
2810c0014855SJack F Vogel 	} else {
2811c0014855SJack F Vogel 		if ((vfta & targetbit)) {
2812c0014855SJack F Vogel 			vfta &= ~targetbit;
2813c0014855SJack F Vogel 			vfta_changed = TRUE;
2814c0014855SJack F Vogel 		}
2815c0014855SJack F Vogel 	}
28162969bf0eSJack F Vogel 
28172969bf0eSJack F Vogel 	/* Part 2
28182969bf0eSJack F Vogel 	 * If VT Mode is set
28192969bf0eSJack F Vogel 	 *   Either vlan_on
28202969bf0eSJack F Vogel 	 *     make sure the vlan is in VLVF
28212969bf0eSJack F Vogel 	 *     set the vind bit in the matching VLVFB
28222969bf0eSJack F Vogel 	 *   Or !vlan_on
28232969bf0eSJack F Vogel 	 *     clear the pool bit and possibly the vind
28242969bf0eSJack F Vogel 	 */
28252969bf0eSJack F Vogel 	vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
28262969bf0eSJack F Vogel 	if (vt & IXGBE_VT_CTL_VT_ENABLE) {
2827c0014855SJack F Vogel 		s32 vlvf_index;
2828c0014855SJack F Vogel 
2829c0014855SJack F Vogel 		vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
2830c0014855SJack F Vogel 		if (vlvf_index < 0)
2831c0014855SJack F Vogel 			return vlvf_index;
28322969bf0eSJack F Vogel 
28332969bf0eSJack F Vogel 		if (vlan_on) {
28342969bf0eSJack F Vogel 			/* set the pool bit */
28352969bf0eSJack F Vogel 			if (vind < 32) {
28362969bf0eSJack F Vogel 				bits = IXGBE_READ_REG(hw,
2837c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2));
28382969bf0eSJack F Vogel 				bits |= (1 << vind);
28392969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw,
2840c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2),
28412969bf0eSJack F Vogel 						bits);
28422969bf0eSJack F Vogel 			} else {
28432969bf0eSJack F Vogel 				bits = IXGBE_READ_REG(hw,
2844c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1));
2845c0014855SJack F Vogel 				bits |= (1 << (vind-32));
28462969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw,
2847c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1),
28482969bf0eSJack F Vogel 						bits);
28492969bf0eSJack F Vogel 			}
28502969bf0eSJack F Vogel 		} else {
28512969bf0eSJack F Vogel 			/* clear the pool bit */
28522969bf0eSJack F Vogel 			if (vind < 32) {
28532969bf0eSJack F Vogel 				bits = IXGBE_READ_REG(hw,
2854c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2));
28552969bf0eSJack F Vogel 				bits &= ~(1 << vind);
28562969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw,
2857c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2),
28582969bf0eSJack F Vogel 						bits);
28592969bf0eSJack F Vogel 				bits |= IXGBE_READ_REG(hw,
2860c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1));
28612969bf0eSJack F Vogel 			} else {
28622969bf0eSJack F Vogel 				bits = IXGBE_READ_REG(hw,
2863c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1));
2864c0014855SJack F Vogel 				bits &= ~(1 << (vind-32));
28652969bf0eSJack F Vogel 				IXGBE_WRITE_REG(hw,
2866c0014855SJack F Vogel 						IXGBE_VLVFB((vlvf_index*2)+1),
28672969bf0eSJack F Vogel 						bits);
28682969bf0eSJack F Vogel 				bits |= IXGBE_READ_REG(hw,
2869c0014855SJack F Vogel 						IXGBE_VLVFB(vlvf_index*2));
28702969bf0eSJack F Vogel 			}
28712969bf0eSJack F Vogel 		}
28722969bf0eSJack F Vogel 
2873c0014855SJack F Vogel 		/*
2874c0014855SJack F Vogel 		 * If there are still bits set in the VLVFB registers
2875c0014855SJack F Vogel 		 * for the VLAN ID indicated we need to see if the
2876c0014855SJack F Vogel 		 * caller is requesting that we clear the VFTA entry bit.
2877c0014855SJack F Vogel 		 * If the caller has requested that we clear the VFTA
2878c0014855SJack F Vogel 		 * entry bit but there are still pools/VFs using this VLAN
2879c0014855SJack F Vogel 		 * ID entry then ignore the request.  We're not worried
2880c0014855SJack F Vogel 		 * about the case where we're turning the VFTA VLAN ID
2881c0014855SJack F Vogel 		 * entry bit on, only when requested to turn it off as
2882c0014855SJack F Vogel 		 * there may be multiple pools and/or VFs using the
2883c0014855SJack F Vogel 		 * VLAN ID entry.  In that case we cannot clear the
2884c0014855SJack F Vogel 		 * VFTA bit until all pools/VFs using that VLAN ID have also
2885c0014855SJack F Vogel 		 * been cleared.  This will be indicated by "bits" being
2886c0014855SJack F Vogel 		 * zero.
2887c0014855SJack F Vogel 		 */
2888c0014855SJack F Vogel 		if (bits) {
2889c0014855SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index),
28902969bf0eSJack F Vogel 					(IXGBE_VLVF_VIEN | vlan));
2891c0014855SJack F Vogel 			if (!vlan_on) {
2892c0014855SJack F Vogel 				/* someone wants to clear the vfta entry
2893c0014855SJack F Vogel 				 * but some pools/VFs are still using it.
2894c0014855SJack F Vogel 				 * Ignore it. */
2895c0014855SJack F Vogel 				vfta_changed = FALSE;
28962969bf0eSJack F Vogel 			}
2897c0014855SJack F Vogel 		}
2898c0014855SJack F Vogel 		else
2899c0014855SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
2900c0014855SJack F Vogel 	}
2901c0014855SJack F Vogel 
2902c0014855SJack F Vogel 	if (vfta_changed)
2903c0014855SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
2904c0014855SJack F Vogel 
29052969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
29062969bf0eSJack F Vogel }
29072969bf0eSJack F Vogel 
29082969bf0eSJack F Vogel /**
29092969bf0eSJack F Vogel  *  ixgbe_clear_vfta_generic - Clear VLAN filter table
29102969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
29112969bf0eSJack F Vogel  *
29122969bf0eSJack F Vogel  *  Clears the VLAN filer table, and the VMDq index associated with the filter
29132969bf0eSJack F Vogel  **/
29142969bf0eSJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
29152969bf0eSJack F Vogel {
29162969bf0eSJack F Vogel 	u32 offset;
29172969bf0eSJack F Vogel 
29182969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_clear_vfta_generic");
29192969bf0eSJack F Vogel 
29202969bf0eSJack F Vogel 	for (offset = 0; offset < hw->mac.vft_size; offset++)
29212969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
29222969bf0eSJack F Vogel 
29232969bf0eSJack F Vogel 	for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
29242969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
29252969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0);
29262969bf0eSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0);
29272969bf0eSJack F Vogel 	}
29282969bf0eSJack F Vogel 
29292969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
29302969bf0eSJack F Vogel }
29312969bf0eSJack F Vogel 
29322969bf0eSJack F Vogel /**
29332969bf0eSJack F Vogel  *  ixgbe_check_mac_link_generic - Determine link and speed status
29342969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
29352969bf0eSJack F Vogel  *  @speed: pointer to link speed
29362969bf0eSJack F Vogel  *  @link_up: TRUE when link is up
29372969bf0eSJack F Vogel  *  @link_up_wait_to_complete: bool used to wait for link up or not
29382969bf0eSJack F Vogel  *
29392969bf0eSJack F Vogel  *  Reads the links register to determine if link is up and the current speed
29402969bf0eSJack F Vogel  **/
29412969bf0eSJack F Vogel s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
29422969bf0eSJack F Vogel                                  bool *link_up, bool link_up_wait_to_complete)
29432969bf0eSJack F Vogel {
2944c0014855SJack F Vogel 	u32 links_reg, links_orig;
29452969bf0eSJack F Vogel 	u32 i;
29462969bf0eSJack F Vogel 
29472969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_check_mac_link_generic");
29482969bf0eSJack F Vogel 
2949c0014855SJack F Vogel 	/* clear the old state */
2950c0014855SJack F Vogel 	links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
2951c0014855SJack F Vogel 
29522969bf0eSJack F Vogel 	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
2953c0014855SJack F Vogel 
2954c0014855SJack F Vogel 	if (links_orig != links_reg) {
2955c0014855SJack F Vogel 		DEBUGOUT2("LINKS changed from %08X to %08X\n",
2956c0014855SJack F Vogel 		          links_orig, links_reg);
2957c0014855SJack F Vogel 	}
2958c0014855SJack F Vogel 
29592969bf0eSJack F Vogel 	if (link_up_wait_to_complete) {
29602969bf0eSJack F Vogel 		for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
29612969bf0eSJack F Vogel 			if (links_reg & IXGBE_LINKS_UP) {
29622969bf0eSJack F Vogel 				*link_up = TRUE;
29632969bf0eSJack F Vogel 				break;
29642969bf0eSJack F Vogel 			} else {
29652969bf0eSJack F Vogel 				*link_up = FALSE;
29662969bf0eSJack F Vogel 			}
29672969bf0eSJack F Vogel 			msec_delay(100);
29682969bf0eSJack F Vogel 			links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
29692969bf0eSJack F Vogel 		}
29702969bf0eSJack F Vogel 	} else {
29712969bf0eSJack F Vogel 		if (links_reg & IXGBE_LINKS_UP)
29722969bf0eSJack F Vogel 			*link_up = TRUE;
29732969bf0eSJack F Vogel 		else
29742969bf0eSJack F Vogel 			*link_up = FALSE;
29752969bf0eSJack F Vogel 	}
29762969bf0eSJack F Vogel 
29772969bf0eSJack F Vogel 	if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
29782969bf0eSJack F Vogel 	    IXGBE_LINKS_SPEED_10G_82599)
29792969bf0eSJack F Vogel 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
29802969bf0eSJack F Vogel 	else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
29812969bf0eSJack F Vogel 	         IXGBE_LINKS_SPEED_1G_82599)
29822969bf0eSJack F Vogel 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
29832969bf0eSJack F Vogel 	else
29842969bf0eSJack F Vogel 		*speed = IXGBE_LINK_SPEED_100_FULL;
29852969bf0eSJack F Vogel 
29862969bf0eSJack F Vogel 	/* if link is down, zero out the current_mode */
29872969bf0eSJack F Vogel 	if (*link_up == FALSE) {
29882969bf0eSJack F Vogel 		hw->fc.current_mode = ixgbe_fc_none;
29892969bf0eSJack F Vogel 		hw->fc.fc_was_autonegged = FALSE;
29902969bf0eSJack F Vogel 	}
29912969bf0eSJack F Vogel 
29922969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
29932969bf0eSJack F Vogel }
29942969bf0eSJack F Vogel 
29952969bf0eSJack F Vogel /**
29962969bf0eSJack F Vogel  *  ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from
29972969bf0eSJack F Vogel  *  the EEPROM
29982969bf0eSJack F Vogel  *  @hw: pointer to hardware structure
29992969bf0eSJack F Vogel  *  @wwnn_prefix: the alternative WWNN prefix
30002969bf0eSJack F Vogel  *  @wwpn_prefix: the alternative WWPN prefix
30012969bf0eSJack F Vogel  *
30022969bf0eSJack F Vogel  *  This function will read the EEPROM from the alternative SAN MAC address
30032969bf0eSJack F Vogel  *  block to check the support for the alternative WWNN/WWPN prefix support.
30042969bf0eSJack F Vogel  **/
30052969bf0eSJack F Vogel s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
30062969bf0eSJack F Vogel                                  u16 *wwpn_prefix)
30072969bf0eSJack F Vogel {
30082969bf0eSJack F Vogel 	u16 offset, caps;
30092969bf0eSJack F Vogel 	u16 alt_san_mac_blk_offset;
30102969bf0eSJack F Vogel 
30112969bf0eSJack F Vogel 	DEBUGFUNC("ixgbe_get_wwn_prefix_generic");
30122969bf0eSJack F Vogel 
30132969bf0eSJack F Vogel 	/* clear output first */
30142969bf0eSJack F Vogel 	*wwnn_prefix = 0xFFFF;
30152969bf0eSJack F Vogel 	*wwpn_prefix = 0xFFFF;
30162969bf0eSJack F Vogel 
30172969bf0eSJack F Vogel 	/* check if alternative SAN MAC is supported */
30182969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR,
30192969bf0eSJack F Vogel 	                    &alt_san_mac_blk_offset);
30202969bf0eSJack F Vogel 
30212969bf0eSJack F Vogel 	if ((alt_san_mac_blk_offset == 0) ||
30222969bf0eSJack F Vogel 	    (alt_san_mac_blk_offset == 0xFFFF))
30232969bf0eSJack F Vogel 		goto wwn_prefix_out;
30242969bf0eSJack F Vogel 
30252969bf0eSJack F Vogel 	/* check capability in alternative san mac address block */
30262969bf0eSJack F Vogel 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
30272969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, offset, &caps);
30282969bf0eSJack F Vogel 	if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
30292969bf0eSJack F Vogel 		goto wwn_prefix_out;
30302969bf0eSJack F Vogel 
30312969bf0eSJack F Vogel 	/* get the corresponding prefix for WWNN/WWPN */
30322969bf0eSJack F Vogel 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
30332969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, offset, wwnn_prefix);
30342969bf0eSJack F Vogel 
30352969bf0eSJack F Vogel 	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
30362969bf0eSJack F Vogel 	hw->eeprom.ops.read(hw, offset, wwpn_prefix);
30372969bf0eSJack F Vogel 
30382969bf0eSJack F Vogel wwn_prefix_out:
30392969bf0eSJack F Vogel 	return IXGBE_SUCCESS;
30402969bf0eSJack F Vogel }
3041