xref: /freebsd/sys/dev/ixgbe/ixgbe_common.c (revision 13705f88fa0048f66dfd76ca4037bb1c0bf1eb07)
113705f88SJack F Vogel /*******************************************************************************
213705f88SJack F Vogel 
313705f88SJack F Vogel   Copyright (c) 2001-2007, 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 
3213705f88SJack 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_poll_eeprom_eerd_done(struct ixgbe_hw *hw);
3913705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
4013705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
4113705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
4213705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw);
4313705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw);
4413705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
4513705f88SJack F Vogel 					u16 count);
4613705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count);
4713705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
4813705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
4913705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
5013705f88SJack F Vogel static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
5113705f88SJack F Vogel 
5213705f88SJack F Vogel static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index);
5313705f88SJack F Vogel static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
5413705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
5513705f88SJack F Vogel void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr);
5613705f88SJack F Vogel 
5713705f88SJack F Vogel /**
5813705f88SJack F Vogel  *  ixgbe_assign_func_pointers_generic - Set generic func ptrs
5913705f88SJack F Vogel  *  @hw: pointer to hardware structure
6013705f88SJack F Vogel  *
6113705f88SJack F Vogel  *  Assigns generic function pointers.  Adapter-specific functions can
6213705f88SJack F Vogel  *  override the assignment of generic function pointers by assigning
6313705f88SJack F Vogel  *  their own adapter-specific function pointers.
6413705f88SJack F Vogel  **/
6513705f88SJack F Vogel s32 ixgbe_assign_func_pointers_generic(struct ixgbe_hw *hw)
6613705f88SJack F Vogel {
6713705f88SJack F Vogel 	struct ixgbe_functions *f = &hw->func;
6813705f88SJack F Vogel 
6913705f88SJack F Vogel 	f->ixgbe_func_init_hw = &ixgbe_init_hw_generic;
7013705f88SJack F Vogel 	f->ixgbe_func_start_hw = &ixgbe_start_hw_generic;
7113705f88SJack F Vogel 	f->ixgbe_func_clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic;
7213705f88SJack F Vogel 	f->ixgbe_func_get_mac_addr = &ixgbe_get_mac_addr_generic;
7313705f88SJack F Vogel 	f->ixgbe_func_stop_adapter = &ixgbe_stop_adapter_generic;
7413705f88SJack F Vogel 	f->ixgbe_func_get_bus_info = &ixgbe_get_bus_info_generic;
7513705f88SJack F Vogel 	/* LED */
7613705f88SJack F Vogel 	f->ixgbe_func_led_on = &ixgbe_led_on_generic;
7713705f88SJack F Vogel 	f->ixgbe_func_led_off = &ixgbe_led_off_generic;
7813705f88SJack F Vogel 	/* EEPROM */
7913705f88SJack F Vogel 	f->ixgbe_func_init_eeprom_params = &ixgbe_init_eeprom_params_generic;
8013705f88SJack F Vogel 	f->ixgbe_func_read_eeprom = &ixgbe_read_eeprom_bit_bang_generic;
8113705f88SJack F Vogel 	f->ixgbe_func_write_eeprom = &ixgbe_write_eeprom_generic;
8213705f88SJack F Vogel 	f->ixgbe_func_validate_eeprom_checksum =
8313705f88SJack F Vogel 			       &ixgbe_validate_eeprom_checksum_generic;
8413705f88SJack F Vogel 	f->ixgbe_func_update_eeprom_checksum =
8513705f88SJack F Vogel 			       &ixgbe_update_eeprom_checksum_generic;
8613705f88SJack F Vogel 	/* RAR, Multicast, VLAN */
8713705f88SJack F Vogel 	f->ixgbe_func_set_rar = &ixgbe_set_rar_generic;
8813705f88SJack F Vogel 	f->ixgbe_func_init_rx_addrs = &ixgbe_init_rx_addrs_generic;
8913705f88SJack F Vogel 	f->ixgbe_func_update_mc_addr_list = &ixgbe_update_mc_addr_list_generic;
9013705f88SJack F Vogel 	f->ixgbe_func_enable_mc = &ixgbe_enable_mc_generic;
9113705f88SJack F Vogel 	f->ixgbe_func_disable_mc = &ixgbe_disable_mc_generic;
9213705f88SJack F Vogel 	f->ixgbe_func_clear_vfta = &ixgbe_clear_vfta_generic;
9313705f88SJack F Vogel 	f->ixgbe_func_set_vfta = &ixgbe_set_vfta_generic;
9413705f88SJack F Vogel 	f->ixgbe_func_setup_fc = &ixgbe_setup_fc_generic;
9513705f88SJack F Vogel 
9613705f88SJack F Vogel 	return IXGBE_SUCCESS;
9713705f88SJack F Vogel }
9813705f88SJack F Vogel 
9913705f88SJack F Vogel /**
10013705f88SJack F Vogel  *  ixgbe_start_hw_generic - Prepare hardware for TX/RX
10113705f88SJack F Vogel  *  @hw: pointer to hardware structure
10213705f88SJack F Vogel  *
10313705f88SJack F Vogel  *  Starts the hardware by filling the bus info structure and media type, clears
10413705f88SJack F Vogel  *  all on chip counters, initializes receive address registers, multicast
10513705f88SJack F Vogel  *  table, VLAN filter table, calls routine to set up link and flow control
10613705f88SJack F Vogel  *  settings, and leaves transmit and receive units disabled and uninitialized
10713705f88SJack F Vogel  **/
10813705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
10913705f88SJack F Vogel {
11013705f88SJack F Vogel 	u32 ctrl_ext;
11113705f88SJack F Vogel 
11213705f88SJack F Vogel 	/* Set the media type */
11313705f88SJack F Vogel 	hw->phy.media_type = ixgbe_get_media_type(hw);
11413705f88SJack F Vogel 
11513705f88SJack F Vogel 	/* Set bus info */
11613705f88SJack F Vogel 	ixgbe_get_bus_info(hw);
11713705f88SJack F Vogel 
11813705f88SJack F Vogel 	/* Identify the PHY */
11913705f88SJack F Vogel 	ixgbe_identify_phy(hw);
12013705f88SJack F Vogel 
12113705f88SJack F Vogel 	/*
12213705f88SJack F Vogel 	 * Store MAC address from RAR0, clear receive address registers, and
12313705f88SJack F Vogel 	 * clear the multicast table
12413705f88SJack F Vogel 	 */
12513705f88SJack F Vogel 	ixgbe_init_rx_addrs(hw);
12613705f88SJack F Vogel 
12713705f88SJack F Vogel 	/* Clear the VLAN filter table */
12813705f88SJack F Vogel 	ixgbe_clear_vfta(hw);
12913705f88SJack F Vogel 
13013705f88SJack F Vogel 	/* Set up link */
13113705f88SJack F Vogel 	ixgbe_setup_link(hw);
13213705f88SJack F Vogel 
13313705f88SJack F Vogel 	/* Clear statistics registers */
13413705f88SJack F Vogel 	ixgbe_clear_hw_cntrs(hw);
13513705f88SJack F Vogel 
13613705f88SJack F Vogel 	/* Set up flow control */
13713705f88SJack F Vogel 	ixgbe_setup_fc(hw, 0);
13813705f88SJack F Vogel 
13913705f88SJack F Vogel 	/* Set No Snoop Disable */
14013705f88SJack F Vogel 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
14113705f88SJack F Vogel 	ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
14213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
14313705f88SJack F Vogel 
14413705f88SJack F Vogel 	/* Clear adapter stopped flag */
14513705f88SJack F Vogel 	hw->adapter_stopped = FALSE;
14613705f88SJack F Vogel 
14713705f88SJack F Vogel 	return IXGBE_SUCCESS;
14813705f88SJack F Vogel }
14913705f88SJack F Vogel 
15013705f88SJack F Vogel /**
15113705f88SJack F Vogel  *  ixgbe_init_hw_generic - Generic hardware initialization
15213705f88SJack F Vogel  *  @hw: pointer to hardware structure
15313705f88SJack F Vogel  *
15413705f88SJack F Vogel  *  Initialize the hardware by reseting the hardware, filling the bus info
15513705f88SJack F Vogel  *  structure and media type, clears all on chip counters, initializes receive
15613705f88SJack F Vogel  *  address registers, multicast table, VLAN filter table, calls routine to set
15713705f88SJack F Vogel  *  up link and flow control settings, and leaves transmit and receive units
15813705f88SJack F Vogel  *  disabled and uninitialized
15913705f88SJack F Vogel  **/
16013705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
16113705f88SJack F Vogel {
16213705f88SJack F Vogel 	/* Reset the hardware */
16313705f88SJack F Vogel 	ixgbe_reset_hw(hw);
16413705f88SJack F Vogel 
16513705f88SJack F Vogel 	/* Start the HW */
16613705f88SJack F Vogel 	ixgbe_start_hw(hw);
16713705f88SJack F Vogel 
16813705f88SJack F Vogel 	return IXGBE_SUCCESS;
16913705f88SJack F Vogel }
17013705f88SJack F Vogel 
17113705f88SJack F Vogel /**
17213705f88SJack F Vogel  *  ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
17313705f88SJack F Vogel  *  @hw: pointer to hardware structure
17413705f88SJack F Vogel  *
17513705f88SJack F Vogel  *  Clears all hardware statistics counters by reading them from the hardware
17613705f88SJack F Vogel  *  Statistics counters are clear on read.
17713705f88SJack F Vogel  **/
17813705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
17913705f88SJack F Vogel {
18013705f88SJack F Vogel 	u16 i = 0;
18113705f88SJack F Vogel 
18213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_CRCERRS);
18313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ILLERRC);
18413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ERRBC);
18513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MSPDC);
18613705f88SJack F Vogel 	for (i = 0; i < 8; i++)
18713705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_MPC(i));
18813705f88SJack F Vogel 
18913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MLFC);
19013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MRFC);
19113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RLEC);
19213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXONTXC);
19313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXONRXC);
19413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
19513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
19613705f88SJack F Vogel 
19713705f88SJack F Vogel 	for (i = 0; i < 8; i++) {
19813705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
19913705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
20013705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
20113705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
20213705f88SJack F Vogel 	}
20313705f88SJack F Vogel 
20413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC64);
20513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC127);
20613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC255);
20713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC511);
20813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC1023);
20913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC1522);
21013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GPRC);
21113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_BPRC);
21213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MPRC);
21313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GPTC);
21413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GORCL);
21513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GORCH);
21613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GOTCL);
21713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GOTCH);
21813705f88SJack F Vogel 	for (i = 0; i < 8; i++)
21913705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_RNBC(i));
22013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RUC);
22113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RFC);
22213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ROC);
22313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RJC);
22413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPRC);
22513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPDC);
22613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPTC);
22713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TORL);
22813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TORH);
22913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TPR);
23013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TPT);
23113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC64);
23213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC127);
23313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC255);
23413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC511);
23513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC1023);
23613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC1522);
23713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MPTC);
23813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_BPTC);
23913705f88SJack F Vogel 	for (i = 0; i < 16; i++) {
24013705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QPRC(i));
24113705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QBRC(i));
24213705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QPTC(i));
24313705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QBTC(i));
24413705f88SJack F Vogel 	}
24513705f88SJack F Vogel 
24613705f88SJack F Vogel 	return IXGBE_SUCCESS;
24713705f88SJack F Vogel }
24813705f88SJack F Vogel 
24913705f88SJack F Vogel /**
25013705f88SJack F Vogel  *  ixgbe_get_mac_addr_generic - Generic get MAC address
25113705f88SJack F Vogel  *  @hw: pointer to hardware structure
25213705f88SJack F Vogel  *  @mac_addr: Adapter MAC address
25313705f88SJack F Vogel  *
25413705f88SJack F Vogel  *  Reads the adapter's MAC address from first Receive Address Register (RAR0)
25513705f88SJack F Vogel  *  A reset of the adapter must be performed prior to calling this function
25613705f88SJack F Vogel  *  in order for the MAC address to have been loaded from the EEPROM into RAR0
25713705f88SJack F Vogel  **/
25813705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
25913705f88SJack F Vogel {
26013705f88SJack F Vogel 	u32 rar_high;
26113705f88SJack F Vogel 	u32 rar_low;
26213705f88SJack F Vogel 	u16 i;
26313705f88SJack F Vogel 
26413705f88SJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0));
26513705f88SJack F Vogel 	rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0));
26613705f88SJack F Vogel 
26713705f88SJack F Vogel 	for (i = 0; i < 4; i++)
26813705f88SJack F Vogel 		mac_addr[i] = (u8)(rar_low >> (i*8));
26913705f88SJack F Vogel 
27013705f88SJack F Vogel 	for (i = 0; i < 2; i++)
27113705f88SJack F Vogel 		mac_addr[i+4] = (u8)(rar_high >> (i*8));
27213705f88SJack F Vogel 
27313705f88SJack F Vogel 	return IXGBE_SUCCESS;
27413705f88SJack F Vogel }
27513705f88SJack F Vogel 
27613705f88SJack F Vogel /**
27713705f88SJack F Vogel  *  ixgbe_get_bus_info_generic - Generic set PCI bus info
27813705f88SJack F Vogel  *  @hw: pointer to hardware structure
27913705f88SJack F Vogel  *
28013705f88SJack F Vogel  *  Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure
28113705f88SJack F Vogel  **/
28213705f88SJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
28313705f88SJack F Vogel {
28413705f88SJack F Vogel 	u16 link_status;
28513705f88SJack F Vogel 
28613705f88SJack F Vogel 	hw->bus.type = ixgbe_bus_type_pci_express;
28713705f88SJack F Vogel 
28813705f88SJack F Vogel 	/* Get the negotiated link width and speed from PCI config space */
28913705f88SJack F Vogel 	link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS);
29013705f88SJack F Vogel 
29113705f88SJack F Vogel 	switch (link_status & IXGBE_PCI_LINK_WIDTH) {
29213705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_1:
29313705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x1;
29413705f88SJack F Vogel 		break;
29513705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_2:
29613705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x2;
29713705f88SJack F Vogel 		break;
29813705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_4:
29913705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x4;
30013705f88SJack F Vogel 		break;
30113705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_8:
30213705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x8;
30313705f88SJack F Vogel 		break;
30413705f88SJack F Vogel 	default:
30513705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_unknown;
30613705f88SJack F Vogel 		break;
30713705f88SJack F Vogel 	}
30813705f88SJack F Vogel 
30913705f88SJack F Vogel 	switch (link_status & IXGBE_PCI_LINK_SPEED) {
31013705f88SJack F Vogel 	case IXGBE_PCI_LINK_SPEED_2500:
31113705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_2500;
31213705f88SJack F Vogel 		break;
31313705f88SJack F Vogel 	case IXGBE_PCI_LINK_SPEED_5000:
31413705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_5000;
31513705f88SJack F Vogel 		break;
31613705f88SJack F Vogel 	default:
31713705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_unknown;
31813705f88SJack F Vogel 		break;
31913705f88SJack F Vogel 	}
32013705f88SJack F Vogel 
32113705f88SJack F Vogel 	return IXGBE_SUCCESS;
32213705f88SJack F Vogel }
32313705f88SJack F Vogel 
32413705f88SJack F Vogel /**
32513705f88SJack F Vogel  *  ixgbe_stop_adapter_generic - Generic stop TX/RX units
32613705f88SJack F Vogel  *  @hw: pointer to hardware structure
32713705f88SJack F Vogel  *
32813705f88SJack F Vogel  *  Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
32913705f88SJack F Vogel  *  disables transmit and receive units. The adapter_stopped flag is used by
33013705f88SJack F Vogel  *  the shared code and drivers to determine if the adapter is in a stopped
33113705f88SJack F Vogel  *  state and should not touch the hardware.
33213705f88SJack F Vogel  **/
33313705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
33413705f88SJack F Vogel {
33513705f88SJack F Vogel 	u32 number_of_queues;
33613705f88SJack F Vogel 	u32 reg_val;
33713705f88SJack F Vogel 	u16 i;
33813705f88SJack F Vogel 
33913705f88SJack F Vogel 	/*
34013705f88SJack F Vogel 	 * Set the adapter_stopped flag so other driver functions stop touching
34113705f88SJack F Vogel 	 * the hardware
34213705f88SJack F Vogel 	 */
34313705f88SJack F Vogel 	hw->adapter_stopped = TRUE;
34413705f88SJack F Vogel 
34513705f88SJack F Vogel 	/* Disable the receive unit */
34613705f88SJack F Vogel 	reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
34713705f88SJack F Vogel 	reg_val &= ~(IXGBE_RXCTRL_RXEN);
34813705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val);
34913705f88SJack F Vogel 	msec_delay(2);
35013705f88SJack F Vogel 
35113705f88SJack F Vogel 	/* Clear interrupt mask to stop from interrupts being generated */
35213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
35313705f88SJack F Vogel 
35413705f88SJack F Vogel 	/* Clear any pending interrupts */
35513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_EICR);
35613705f88SJack F Vogel 
35713705f88SJack F Vogel 	/* Disable the transmit unit.  Each queue must be disabled. */
35813705f88SJack F Vogel 	number_of_queues = ixgbe_get_num_of_tx_queues(hw);
35913705f88SJack F Vogel 	for (i = 0; i < number_of_queues; i++) {
36013705f88SJack F Vogel 		reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
36113705f88SJack F Vogel 		if (reg_val & IXGBE_TXDCTL_ENABLE) {
36213705f88SJack F Vogel 			reg_val &= ~IXGBE_TXDCTL_ENABLE;
36313705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val);
36413705f88SJack F Vogel 		}
36513705f88SJack F Vogel 	}
36613705f88SJack F Vogel 
36713705f88SJack F Vogel 	return IXGBE_SUCCESS;
36813705f88SJack F Vogel }
36913705f88SJack F Vogel 
37013705f88SJack F Vogel /**
37113705f88SJack F Vogel  *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
37213705f88SJack F Vogel  *  @hw: pointer to hardware structure
37313705f88SJack F Vogel  *  @index: led number to turn on
37413705f88SJack F Vogel  **/
37513705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
37613705f88SJack F Vogel {
37713705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
37813705f88SJack F Vogel 
37913705f88SJack F Vogel 	/* To turn on the LED, set mode to ON. */
38013705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
38113705f88SJack F Vogel 	led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index);
38213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
38313705f88SJack F Vogel 
38413705f88SJack F Vogel 	return IXGBE_SUCCESS;
38513705f88SJack F Vogel }
38613705f88SJack F Vogel 
38713705f88SJack F Vogel /**
38813705f88SJack F Vogel  *  ixgbe_led_off_generic - Turns off the software controllable LEDs.
38913705f88SJack F Vogel  *  @hw: pointer to hardware structure
39013705f88SJack F Vogel  *  @index: led number to turn off
39113705f88SJack F Vogel  **/
39213705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
39313705f88SJack F Vogel {
39413705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
39513705f88SJack F Vogel 
39613705f88SJack F Vogel 	/* To turn off the LED, set mode to OFF. */
39713705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
39813705f88SJack F Vogel 	led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index);
39913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
40013705f88SJack F Vogel 
40113705f88SJack F Vogel 	return IXGBE_SUCCESS;
40213705f88SJack F Vogel }
40313705f88SJack F Vogel 
40413705f88SJack F Vogel 
40513705f88SJack F Vogel /**
40613705f88SJack F Vogel  *  ixgbe_blink_led_start_generic - Blink LED based on index.
40713705f88SJack F Vogel  *  @hw: pointer to hardware structure
40813705f88SJack F Vogel  *  @index: led number to blink
40913705f88SJack F Vogel  **/
41013705f88SJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
41113705f88SJack F Vogel {
41213705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
41313705f88SJack F Vogel 
41413705f88SJack F Vogel 	led_reg |= IXGBE_LED_BLINK(index);
41513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
41613705f88SJack F Vogel 
41713705f88SJack F Vogel 	return IXGBE_SUCCESS;
41813705f88SJack F Vogel }
41913705f88SJack F Vogel 
42013705f88SJack F Vogel /**
42113705f88SJack F Vogel  *  ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
42213705f88SJack F Vogel  *  @hw: pointer to hardware structure
42313705f88SJack F Vogel  *  @index: led number to stop blinking
42413705f88SJack F Vogel  **/
42513705f88SJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
42613705f88SJack F Vogel {
42713705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
42813705f88SJack F Vogel 
42913705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_BLINK(index);
43013705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
43113705f88SJack F Vogel 
43213705f88SJack F Vogel 	return IXGBE_SUCCESS;
43313705f88SJack F Vogel }
43413705f88SJack F Vogel 
43513705f88SJack F Vogel /**
43613705f88SJack F Vogel  *  ixgbe_init_eeprom_params_generic - Initialize EEPROM params
43713705f88SJack F Vogel  *  @hw: pointer to hardware structure
43813705f88SJack F Vogel  *
43913705f88SJack F Vogel  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
44013705f88SJack F Vogel  *  ixgbe_hw struct in order to set up EEPROM access.
44113705f88SJack F Vogel  **/
44213705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
44313705f88SJack F Vogel {
44413705f88SJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
44513705f88SJack F Vogel 	u32 eec;
44613705f88SJack F Vogel 	u16 eeprom_size;
44713705f88SJack F Vogel 
44813705f88SJack F Vogel 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
44913705f88SJack F Vogel 		eeprom->type = ixgbe_eeprom_none;
45013705f88SJack F Vogel 
45113705f88SJack F Vogel 		/*
45213705f88SJack F Vogel 		 * Check for EEPROM present first.
45313705f88SJack F Vogel 		 * If not present leave as none
45413705f88SJack F Vogel 		 */
45513705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
45613705f88SJack F Vogel 		if (eec & IXGBE_EEC_PRES) {
45713705f88SJack F Vogel 			eeprom->type = ixgbe_eeprom_spi;
45813705f88SJack F Vogel 
45913705f88SJack F Vogel 			/*
46013705f88SJack F Vogel 			 * SPI EEPROM is assumed here.  This code would need to
46113705f88SJack F Vogel 			 * change if a future EEPROM is not SPI.
46213705f88SJack F Vogel 			 */
46313705f88SJack F Vogel 			eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
46413705f88SJack F Vogel 					    IXGBE_EEC_SIZE_SHIFT);
46513705f88SJack F Vogel 			eeprom->word_size = 1 << (eeprom_size +
46613705f88SJack F Vogel 						  IXGBE_EEPROM_WORD_SIZE_SHIFT);
46713705f88SJack F Vogel 		}
46813705f88SJack F Vogel 
46913705f88SJack F Vogel 		if (eec & IXGBE_EEC_ADDR_SIZE)
47013705f88SJack F Vogel 			eeprom->address_bits = 16;
47113705f88SJack F Vogel 		else
47213705f88SJack F Vogel 			eeprom->address_bits = 8;
47313705f88SJack F Vogel 		DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: "
47413705f88SJack F Vogel 			  "%d\n", eeprom->type, eeprom->word_size,
47513705f88SJack F Vogel 			  eeprom->address_bits);
47613705f88SJack F Vogel 	}
47713705f88SJack F Vogel 
47813705f88SJack F Vogel 	return IXGBE_SUCCESS;
47913705f88SJack F Vogel }
48013705f88SJack F Vogel 
48113705f88SJack F Vogel /**
48213705f88SJack F Vogel  *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
48313705f88SJack F Vogel  *  @hw: pointer to hardware structure
48413705f88SJack F Vogel  *  @offset: offset within the EEPROM to be written to
48513705f88SJack F Vogel  *  @data: 16 bit word to be written to the EEPROM
48613705f88SJack F Vogel  *
48713705f88SJack F Vogel  *  If ixgbe_eeprom_update_checksum is not called after this function, the
48813705f88SJack F Vogel  *  EEPROM will most likely contain an invalid checksum.
48913705f88SJack F Vogel  **/
49013705f88SJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
49113705f88SJack F Vogel {
49213705f88SJack F Vogel 	s32 status;
49313705f88SJack F Vogel 	u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
49413705f88SJack F Vogel 
49513705f88SJack F Vogel 	/* Prepare the EEPROM for writing  */
49613705f88SJack F Vogel 	status = ixgbe_acquire_eeprom(hw);
49713705f88SJack F Vogel 
49813705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
49913705f88SJack F Vogel 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
50013705f88SJack F Vogel 			ixgbe_release_eeprom(hw);
50113705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
50213705f88SJack F Vogel 		}
50313705f88SJack F Vogel 	}
50413705f88SJack F Vogel 
50513705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
50613705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
50713705f88SJack F Vogel 
50813705f88SJack F Vogel 		/*  Send the WRITE ENABLE command (8 bit opcode )  */
50913705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI,
51013705f88SJack F Vogel 					    IXGBE_EEPROM_OPCODE_BITS);
51113705f88SJack F Vogel 
51213705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
51313705f88SJack F Vogel 
51413705f88SJack F Vogel 		/*
51513705f88SJack F Vogel 		 * Some SPI eeproms use the 8th address bit embedded in the
51613705f88SJack F Vogel 		 * opcode
51713705f88SJack F Vogel 		 */
51813705f88SJack F Vogel 		if ((hw->eeprom.address_bits == 8) && (offset >= 128))
51913705f88SJack F Vogel 			write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
52013705f88SJack F Vogel 
52113705f88SJack F Vogel 		/* Send the Write command (8-bit opcode + addr) */
52213705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, write_opcode,
52313705f88SJack F Vogel 					    IXGBE_EEPROM_OPCODE_BITS);
52413705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
52513705f88SJack F Vogel 					    hw->eeprom.address_bits);
52613705f88SJack F Vogel 
52713705f88SJack F Vogel 		/* Send the data */
52813705f88SJack F Vogel 		data = (data >> 8) | (data << 8);
52913705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, data, 16);
53013705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
53113705f88SJack F Vogel 
53213705f88SJack F Vogel 		msec_delay(10);
53313705f88SJack F Vogel 
53413705f88SJack F Vogel 		/* Done with writing - release the EEPROM */
53513705f88SJack F Vogel 		ixgbe_release_eeprom(hw);
53613705f88SJack F Vogel 	}
53713705f88SJack F Vogel 
53813705f88SJack F Vogel 	return status;
53913705f88SJack F Vogel }
54013705f88SJack F Vogel 
54113705f88SJack F Vogel /**
54213705f88SJack F Vogel  *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
54313705f88SJack F Vogel  *  @hw: pointer to hardware structure
54413705f88SJack F Vogel  *  @offset: offset within the EEPROM to be read
54513705f88SJack F Vogel  *  @data: read 16 bit value from EEPROM
54613705f88SJack F Vogel  *
54713705f88SJack F Vogel  *  Reads 16 bit value from EEPROM through bit-bang method
54813705f88SJack F Vogel  **/
54913705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
55013705f88SJack F Vogel 				       u16 *data)
55113705f88SJack F Vogel {
55213705f88SJack F Vogel 	s32 status;
55313705f88SJack F Vogel 	u16 word_in;
55413705f88SJack F Vogel 	u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
55513705f88SJack F Vogel 
55613705f88SJack F Vogel 	/* Prepare the EEPROM for reading  */
55713705f88SJack F Vogel 	status = ixgbe_acquire_eeprom(hw);
55813705f88SJack F Vogel 
55913705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
56013705f88SJack F Vogel 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
56113705f88SJack F Vogel 			ixgbe_release_eeprom(hw);
56213705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
56313705f88SJack F Vogel 		}
56413705f88SJack F Vogel 	}
56513705f88SJack F Vogel 
56613705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
56713705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
56813705f88SJack F Vogel 
56913705f88SJack F Vogel 		/*
57013705f88SJack F Vogel 		 * Some SPI eeproms use the 8th address bit embedded in the
57113705f88SJack F Vogel 		 * opcode
57213705f88SJack F Vogel 		 */
57313705f88SJack F Vogel 		if ((hw->eeprom.address_bits == 8) && (offset >= 128))
57413705f88SJack F Vogel 			read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
57513705f88SJack F Vogel 
57613705f88SJack F Vogel 		/* Send the READ command (opcode + addr) */
57713705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, read_opcode,
57813705f88SJack F Vogel 					    IXGBE_EEPROM_OPCODE_BITS);
57913705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
58013705f88SJack F Vogel 					    hw->eeprom.address_bits);
58113705f88SJack F Vogel 
58213705f88SJack F Vogel 		/* Read the data. */
58313705f88SJack F Vogel 		word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
58413705f88SJack F Vogel 		*data = (word_in >> 8) | (word_in << 8);
58513705f88SJack F Vogel 
58613705f88SJack F Vogel 		/* End this read operation */
58713705f88SJack F Vogel 		ixgbe_release_eeprom(hw);
58813705f88SJack F Vogel 	}
58913705f88SJack F Vogel 
59013705f88SJack F Vogel 	return status;
59113705f88SJack F Vogel }
59213705f88SJack F Vogel 
59313705f88SJack F Vogel /**
59413705f88SJack F Vogel  *  ixgbe_read_eeprom_generic - Read EEPROM word using EERD
59513705f88SJack F Vogel  *  @hw: pointer to hardware structure
59613705f88SJack F Vogel  *  @offset: offset of  word in the EEPROM to read
59713705f88SJack F Vogel  *  @data: word read from the EEPROM
59813705f88SJack F Vogel  *
59913705f88SJack F Vogel  *  Reads a 16 bit word from the EEPROM using the EERD register.
60013705f88SJack F Vogel  **/
60113705f88SJack F Vogel s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
60213705f88SJack F Vogel {
60313705f88SJack F Vogel 	u32 eerd;
60413705f88SJack F Vogel 	s32 status;
60513705f88SJack F Vogel 
60613705f88SJack F Vogel 	eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) +
60713705f88SJack F Vogel 	       IXGBE_EEPROM_READ_REG_START;
60813705f88SJack F Vogel 
60913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
61013705f88SJack F Vogel 	status = ixgbe_poll_eeprom_eerd_done(hw);
61113705f88SJack F Vogel 
61213705f88SJack F Vogel 	if (status == IXGBE_SUCCESS)
61313705f88SJack F Vogel 		*data = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
61413705f88SJack F Vogel 			IXGBE_EEPROM_READ_REG_DATA);
61513705f88SJack F Vogel 	else
61613705f88SJack F Vogel 		DEBUGOUT("Eeprom read timed out\n");
61713705f88SJack F Vogel 
61813705f88SJack F Vogel 	return status;
61913705f88SJack F Vogel }
62013705f88SJack F Vogel 
62113705f88SJack F Vogel /**
62213705f88SJack F Vogel  *  ixgbe_poll_eeprom_eerd_done - Poll EERD status
62313705f88SJack F Vogel  *  @hw: pointer to hardware structure
62413705f88SJack F Vogel  *
62513705f88SJack F Vogel  *  Polls the status bit (bit 1) of the EERD to determine when the read is done.
62613705f88SJack F Vogel  **/
62713705f88SJack F Vogel static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw)
62813705f88SJack F Vogel {
62913705f88SJack F Vogel 	u32 i;
63013705f88SJack F Vogel 	u32 reg;
63113705f88SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM;
63213705f88SJack F Vogel 
63313705f88SJack F Vogel 	for (i = 0; i < IXGBE_EERD_ATTEMPTS; i++) {
63413705f88SJack F Vogel 		reg = IXGBE_READ_REG(hw, IXGBE_EERD);
63513705f88SJack F Vogel 		if (reg & IXGBE_EEPROM_READ_REG_DONE) {
63613705f88SJack F Vogel 			status = IXGBE_SUCCESS;
63713705f88SJack F Vogel 			break;
63813705f88SJack F Vogel 		}
63913705f88SJack F Vogel 		usec_delay(5);
64013705f88SJack F Vogel 	}
64113705f88SJack F Vogel 	return status;
64213705f88SJack F Vogel }
64313705f88SJack F Vogel 
64413705f88SJack F Vogel /**
64513705f88SJack F Vogel  *  ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang
64613705f88SJack F Vogel  *  @hw: pointer to hardware structure
64713705f88SJack F Vogel  *
64813705f88SJack F Vogel  *  Prepares EEPROM for access using bit-bang method. This function should
64913705f88SJack F Vogel  *  be called before issuing a command to the EEPROM.
65013705f88SJack F Vogel  **/
65113705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
65213705f88SJack F Vogel {
65313705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
65413705f88SJack F Vogel 	u32 eec;
65513705f88SJack F Vogel 	u32 i;
65613705f88SJack F Vogel 
65713705f88SJack F Vogel 	if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS)
65813705f88SJack F Vogel 		status = IXGBE_ERR_SWFW_SYNC;
65913705f88SJack F Vogel 
66013705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
66113705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
66213705f88SJack F Vogel 
66313705f88SJack F Vogel 		/* Request EEPROM Access */
66413705f88SJack F Vogel 		eec |= IXGBE_EEC_REQ;
66513705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
66613705f88SJack F Vogel 
66713705f88SJack F Vogel 		for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
66813705f88SJack F Vogel 			eec = IXGBE_READ_REG(hw, IXGBE_EEC);
66913705f88SJack F Vogel 			if (eec & IXGBE_EEC_GNT)
67013705f88SJack F Vogel 				break;
67113705f88SJack F Vogel 			usec_delay(5);
67213705f88SJack F Vogel 		}
67313705f88SJack F Vogel 
67413705f88SJack F Vogel 		/* Release if grant not aquired */
67513705f88SJack F Vogel 		if (!(eec & IXGBE_EEC_GNT)) {
67613705f88SJack F Vogel 			eec &= ~IXGBE_EEC_REQ;
67713705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
67813705f88SJack F Vogel 			DEBUGOUT("Could not acquire EEPROM grant\n");
67913705f88SJack F Vogel 
68013705f88SJack F Vogel 			ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
68113705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
68213705f88SJack F Vogel 		}
68313705f88SJack F Vogel 	}
68413705f88SJack F Vogel 
68513705f88SJack F Vogel 	/* Setup EEPROM for Read/Write */
68613705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
68713705f88SJack F Vogel 		/* Clear CS and SK */
68813705f88SJack F Vogel 		eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
68913705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
69013705f88SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
69113705f88SJack F Vogel 		usec_delay(1);
69213705f88SJack F Vogel 	}
69313705f88SJack F Vogel 	return status;
69413705f88SJack F Vogel }
69513705f88SJack F Vogel 
69613705f88SJack F Vogel /**
69713705f88SJack F Vogel  *  ixgbe_get_eeprom_semaphore - Get hardware semaphore
69813705f88SJack F Vogel  *  @hw: pointer to hardware structure
69913705f88SJack F Vogel  *
70013705f88SJack F Vogel  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
70113705f88SJack F Vogel  **/
70213705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
70313705f88SJack F Vogel {
70413705f88SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM;
70513705f88SJack F Vogel 	u32 timeout;
70613705f88SJack F Vogel 	u32 i;
70713705f88SJack F Vogel 	u32 swsm;
70813705f88SJack F Vogel 
70913705f88SJack F Vogel 	/* Set timeout value based on size of EEPROM */
71013705f88SJack F Vogel 	timeout = hw->eeprom.word_size + 1;
71113705f88SJack F Vogel 
71213705f88SJack F Vogel 	/* Get SMBI software semaphore between device drivers first */
71313705f88SJack F Vogel 	for (i = 0; i < timeout; i++) {
71413705f88SJack F Vogel 		/*
71513705f88SJack F Vogel 		 * If the SMBI bit is 0 when we read it, then the bit will be
71613705f88SJack F Vogel 		 * set and we have the semaphore
71713705f88SJack F Vogel 		 */
71813705f88SJack F Vogel 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
71913705f88SJack F Vogel 		if (!(swsm & IXGBE_SWSM_SMBI)) {
72013705f88SJack F Vogel 			status = IXGBE_SUCCESS;
72113705f88SJack F Vogel 			break;
72213705f88SJack F Vogel 		}
72313705f88SJack F Vogel 		msec_delay(1);
72413705f88SJack F Vogel 	}
72513705f88SJack F Vogel 
72613705f88SJack F Vogel 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
72713705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
72813705f88SJack F Vogel 		for (i = 0; i < timeout; i++) {
72913705f88SJack F Vogel 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
73013705f88SJack F Vogel 
73113705f88SJack F Vogel 			/* Set the SW EEPROM semaphore bit to request access */
73213705f88SJack F Vogel 			swsm |= IXGBE_SWSM_SWESMBI;
73313705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
73413705f88SJack F Vogel 
73513705f88SJack F Vogel 			/*
73613705f88SJack F Vogel 			 * If we set the bit successfully then we got the
73713705f88SJack F Vogel 			 * semaphore.
73813705f88SJack F Vogel 			 */
73913705f88SJack F Vogel 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
74013705f88SJack F Vogel 			if (swsm & IXGBE_SWSM_SWESMBI)
74113705f88SJack F Vogel 				break;
74213705f88SJack F Vogel 
74313705f88SJack F Vogel 			usec_delay(50);
74413705f88SJack F Vogel 		}
74513705f88SJack F Vogel 
74613705f88SJack F Vogel 		/*
74713705f88SJack F Vogel 		 * Release semaphores and return error if SW EEPROM semaphore
74813705f88SJack F Vogel 		 * was not granted because we don't have access to the EEPROM
74913705f88SJack F Vogel 		 */
75013705f88SJack F Vogel 		if (i >= timeout) {
75113705f88SJack F Vogel 			DEBUGOUT("Driver can't access the Eeprom - Semaphore "
75213705f88SJack F Vogel 				 "not granted.\n");
75313705f88SJack F Vogel 			ixgbe_release_eeprom_semaphore(hw);
75413705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
75513705f88SJack F Vogel 		}
75613705f88SJack F Vogel 	}
75713705f88SJack F Vogel 
75813705f88SJack F Vogel 	return status;
75913705f88SJack F Vogel }
76013705f88SJack F Vogel 
76113705f88SJack F Vogel /**
76213705f88SJack F Vogel  *  ixgbe_release_eeprom_semaphore - Release hardware semaphore
76313705f88SJack F Vogel  *  @hw: pointer to hardware structure
76413705f88SJack F Vogel  *
76513705f88SJack F Vogel  *  This function clears hardware semaphore bits.
76613705f88SJack F Vogel  **/
76713705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
76813705f88SJack F Vogel {
76913705f88SJack F Vogel 	u32 swsm;
77013705f88SJack F Vogel 
77113705f88SJack F Vogel 	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
77213705f88SJack F Vogel 
77313705f88SJack F Vogel 	/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
77413705f88SJack F Vogel 	swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI);
77513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
77613705f88SJack F Vogel }
77713705f88SJack F Vogel 
77813705f88SJack F Vogel /**
77913705f88SJack F Vogel  *  ixgbe_ready_eeprom - Polls for EEPROM ready
78013705f88SJack F Vogel  *  @hw: pointer to hardware structure
78113705f88SJack F Vogel  **/
78213705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
78313705f88SJack F Vogel {
78413705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
78513705f88SJack F Vogel 	u16 i;
78613705f88SJack F Vogel 	u8 spi_stat_reg;
78713705f88SJack F Vogel 
78813705f88SJack F Vogel 	/*
78913705f88SJack F Vogel 	 * Read "Status Register" repeatedly until the LSB is cleared.  The
79013705f88SJack F Vogel 	 * EEPROM will signal that the command has been completed by clearing
79113705f88SJack F Vogel 	 * bit 0 of the internal status register.  If it's not cleared within
79213705f88SJack F Vogel 	 * 5 milliseconds, then error out.
79313705f88SJack F Vogel 	 */
79413705f88SJack F Vogel 	for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) {
79513705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI,
79613705f88SJack F Vogel 					    IXGBE_EEPROM_OPCODE_BITS);
79713705f88SJack F Vogel 		spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8);
79813705f88SJack F Vogel 		if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI))
79913705f88SJack F Vogel 			break;
80013705f88SJack F Vogel 
80113705f88SJack F Vogel 		usec_delay(5);
80213705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
80313705f88SJack F Vogel 	};
80413705f88SJack F Vogel 
80513705f88SJack F Vogel 	/*
80613705f88SJack F Vogel 	 * On some parts, SPI write time could vary from 0-20mSec on 3.3V
80713705f88SJack F Vogel 	 * devices (and only 0-5mSec on 5V devices)
80813705f88SJack F Vogel 	 */
80913705f88SJack F Vogel 	if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
81013705f88SJack F Vogel 		DEBUGOUT("SPI EEPROM Status error\n");
81113705f88SJack F Vogel 		status = IXGBE_ERR_EEPROM;
81213705f88SJack F Vogel 	}
81313705f88SJack F Vogel 
81413705f88SJack F Vogel 	return status;
81513705f88SJack F Vogel }
81613705f88SJack F Vogel 
81713705f88SJack F Vogel /**
81813705f88SJack F Vogel  *  ixgbe_standby_eeprom - Returns EEPROM to a "standby" state
81913705f88SJack F Vogel  *  @hw: pointer to hardware structure
82013705f88SJack F Vogel  **/
82113705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
82213705f88SJack F Vogel {
82313705f88SJack F Vogel 	u32 eec;
82413705f88SJack F Vogel 
82513705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
82613705f88SJack F Vogel 
82713705f88SJack F Vogel 	/* Toggle CS to flush commands */
82813705f88SJack F Vogel 	eec |= IXGBE_EEC_CS;
82913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
83013705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
83113705f88SJack F Vogel 	usec_delay(1);
83213705f88SJack F Vogel 	eec &= ~IXGBE_EEC_CS;
83313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
83413705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
83513705f88SJack F Vogel 	usec_delay(1);
83613705f88SJack F Vogel }
83713705f88SJack F Vogel 
83813705f88SJack F Vogel /**
83913705f88SJack F Vogel  *  ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM.
84013705f88SJack F Vogel  *  @hw: pointer to hardware structure
84113705f88SJack F Vogel  *  @data: data to send to the EEPROM
84213705f88SJack F Vogel  *  @count: number of bits to shift out
84313705f88SJack F Vogel  **/
84413705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
84513705f88SJack F Vogel 					u16 count)
84613705f88SJack F Vogel {
84713705f88SJack F Vogel 	u32 eec;
84813705f88SJack F Vogel 	u32 mask;
84913705f88SJack F Vogel 	u32 i;
85013705f88SJack F Vogel 
85113705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
85213705f88SJack F Vogel 
85313705f88SJack F Vogel 	/*
85413705f88SJack F Vogel 	 * Mask is used to shift "count" bits of "data" out to the EEPROM
85513705f88SJack F Vogel 	 * one bit at a time.  Determine the starting bit based on count
85613705f88SJack F Vogel 	 */
85713705f88SJack F Vogel 	mask = 0x01 << (count - 1);
85813705f88SJack F Vogel 
85913705f88SJack F Vogel 	for (i = 0; i < count; i++) {
86013705f88SJack F Vogel 		/*
86113705f88SJack F Vogel 		 * A "1" is shifted out to the EEPROM by setting bit "DI" to a
86213705f88SJack F Vogel 		 * "1", and then raising and then lowering the clock (the SK
86313705f88SJack F Vogel 		 * bit controls the clock input to the EEPROM).  A "0" is
86413705f88SJack F Vogel 		 * shifted out to the EEPROM by setting "DI" to "0" and then
86513705f88SJack F Vogel 		 * raising and then lowering the clock.
86613705f88SJack F Vogel 		 */
86713705f88SJack F Vogel 		if (data & mask)
86813705f88SJack F Vogel 			eec |= IXGBE_EEC_DI;
86913705f88SJack F Vogel 		else
87013705f88SJack F Vogel 			eec &= ~IXGBE_EEC_DI;
87113705f88SJack F Vogel 
87213705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
87313705f88SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
87413705f88SJack F Vogel 
87513705f88SJack F Vogel 		usec_delay(1);
87613705f88SJack F Vogel 
87713705f88SJack F Vogel 		ixgbe_raise_eeprom_clk(hw, &eec);
87813705f88SJack F Vogel 		ixgbe_lower_eeprom_clk(hw, &eec);
87913705f88SJack F Vogel 
88013705f88SJack F Vogel 		/*
88113705f88SJack F Vogel 		 * Shift mask to signify next bit of data to shift in to the
88213705f88SJack F Vogel 		 * EEPROM
88313705f88SJack F Vogel 		 */
88413705f88SJack F Vogel 		mask = mask >> 1;
88513705f88SJack F Vogel 	};
88613705f88SJack F Vogel 
88713705f88SJack F Vogel 	/* We leave the "DI" bit set to "0" when we leave this routine. */
88813705f88SJack F Vogel 	eec &= ~IXGBE_EEC_DI;
88913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
89013705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
89113705f88SJack F Vogel }
89213705f88SJack F Vogel 
89313705f88SJack F Vogel /**
89413705f88SJack F Vogel  *  ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
89513705f88SJack F Vogel  *  @hw: pointer to hardware structure
89613705f88SJack F Vogel  **/
89713705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
89813705f88SJack F Vogel {
89913705f88SJack F Vogel 	u32 eec;
90013705f88SJack F Vogel 	u32 i;
90113705f88SJack F Vogel 	u16 data = 0;
90213705f88SJack F Vogel 
90313705f88SJack F Vogel 	/*
90413705f88SJack F Vogel 	 * In order to read a register from the EEPROM, we need to shift
90513705f88SJack F Vogel 	 * 'count' bits in from the EEPROM. Bits are "shifted in" by raising
90613705f88SJack F Vogel 	 * the clock input to the EEPROM (setting the SK bit), and then reading
90713705f88SJack F Vogel 	 * the value of the "DO" bit.  During this "shifting in" process the
90813705f88SJack F Vogel 	 * "DI" bit should always be clear.
90913705f88SJack F Vogel 	 */
91013705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
91113705f88SJack F Vogel 
91213705f88SJack F Vogel 	eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
91313705f88SJack F Vogel 
91413705f88SJack F Vogel 	for (i = 0; i < count; i++) {
91513705f88SJack F Vogel 		data = data << 1;
91613705f88SJack F Vogel 		ixgbe_raise_eeprom_clk(hw, &eec);
91713705f88SJack F Vogel 
91813705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
91913705f88SJack F Vogel 
92013705f88SJack F Vogel 		eec &= ~(IXGBE_EEC_DI);
92113705f88SJack F Vogel 		if (eec & IXGBE_EEC_DO)
92213705f88SJack F Vogel 			data |= 1;
92313705f88SJack F Vogel 
92413705f88SJack F Vogel 		ixgbe_lower_eeprom_clk(hw, &eec);
92513705f88SJack F Vogel 	}
92613705f88SJack F Vogel 
92713705f88SJack F Vogel 	return data;
92813705f88SJack F Vogel }
92913705f88SJack F Vogel 
93013705f88SJack F Vogel /**
93113705f88SJack F Vogel  *  ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input.
93213705f88SJack F Vogel  *  @hw: pointer to hardware structure
93313705f88SJack F Vogel  *  @eec: EEC register's current value
93413705f88SJack F Vogel  **/
93513705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
93613705f88SJack F Vogel {
93713705f88SJack F Vogel 	/*
93813705f88SJack F Vogel 	 * Raise the clock input to the EEPROM
93913705f88SJack F Vogel 	 * (setting the SK bit), then delay
94013705f88SJack F Vogel 	 */
94113705f88SJack F Vogel 	*eec = *eec | IXGBE_EEC_SK;
94213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
94313705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
94413705f88SJack F Vogel 	usec_delay(1);
94513705f88SJack F Vogel }
94613705f88SJack F Vogel 
94713705f88SJack F Vogel /**
94813705f88SJack F Vogel  *  ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input.
94913705f88SJack F Vogel  *  @hw: pointer to hardware structure
95013705f88SJack F Vogel  *  @eecd: EECD's current value
95113705f88SJack F Vogel  **/
95213705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
95313705f88SJack F Vogel {
95413705f88SJack F Vogel 	/*
95513705f88SJack F Vogel 	 * Lower the clock input to the EEPROM (clearing the SK bit), then
95613705f88SJack F Vogel 	 * delay
95713705f88SJack F Vogel 	 */
95813705f88SJack F Vogel 	*eec = *eec & ~IXGBE_EEC_SK;
95913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
96013705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
96113705f88SJack F Vogel 	usec_delay(1);
96213705f88SJack F Vogel }
96313705f88SJack F Vogel 
96413705f88SJack F Vogel /**
96513705f88SJack F Vogel  *  ixgbe_release_eeprom - Release EEPROM, release semaphores
96613705f88SJack F Vogel  *  @hw: pointer to hardware structure
96713705f88SJack F Vogel  **/
96813705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
96913705f88SJack F Vogel {
97013705f88SJack F Vogel 	u32 eec;
97113705f88SJack F Vogel 
97213705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
97313705f88SJack F Vogel 
97413705f88SJack F Vogel 	eec |= IXGBE_EEC_CS;  /* Pull CS high */
97513705f88SJack F Vogel 	eec &= ~IXGBE_EEC_SK; /* Lower SCK */
97613705f88SJack F Vogel 
97713705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
97813705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
97913705f88SJack F Vogel 
98013705f88SJack F Vogel 	usec_delay(1);
98113705f88SJack F Vogel 
98213705f88SJack F Vogel 	/* Stop requesting EEPROM access */
98313705f88SJack F Vogel 	eec &= ~IXGBE_EEC_REQ;
98413705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
98513705f88SJack F Vogel 
98613705f88SJack F Vogel 	ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
98713705f88SJack F Vogel }
98813705f88SJack F Vogel 
98913705f88SJack F Vogel /**
99013705f88SJack F Vogel  *  ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
99113705f88SJack F Vogel  *  @hw: pointer to hardware structure
99213705f88SJack F Vogel  **/
99313705f88SJack F Vogel static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw)
99413705f88SJack F Vogel {
99513705f88SJack F Vogel 	u16 i;
99613705f88SJack F Vogel 	u16 j;
99713705f88SJack F Vogel 	u16 checksum = 0;
99813705f88SJack F Vogel 	u16 length = 0;
99913705f88SJack F Vogel 	u16 pointer = 0;
100013705f88SJack F Vogel 	u16 word = 0;
100113705f88SJack F Vogel 
100213705f88SJack F Vogel 	/* Include 0x0-0x3F in the checksum */
100313705f88SJack F Vogel 	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
100413705f88SJack F Vogel 		if (ixgbe_read_eeprom(hw, i, &word) != IXGBE_SUCCESS) {
100513705f88SJack F Vogel 			DEBUGOUT("EEPROM read failed\n");
100613705f88SJack F Vogel 			break;
100713705f88SJack F Vogel 		}
100813705f88SJack F Vogel 		checksum += word;
100913705f88SJack F Vogel 	}
101013705f88SJack F Vogel 
101113705f88SJack F Vogel 	/* Include all data from pointers except for the fw pointer */
101213705f88SJack F Vogel 	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
101313705f88SJack F Vogel 		ixgbe_read_eeprom(hw, i, &pointer);
101413705f88SJack F Vogel 
101513705f88SJack F Vogel 		/* Make sure the pointer seems valid */
101613705f88SJack F Vogel 		if (pointer != 0xFFFF && pointer != 0) {
101713705f88SJack F Vogel 			ixgbe_read_eeprom(hw, pointer, &length);
101813705f88SJack F Vogel 
101913705f88SJack F Vogel 			if (length != 0xFFFF && length != 0) {
102013705f88SJack F Vogel 				for (j = pointer+1; j <= pointer+length; j++) {
102113705f88SJack F Vogel 					ixgbe_read_eeprom(hw, j, &word);
102213705f88SJack F Vogel 					checksum += word;
102313705f88SJack F Vogel 				}
102413705f88SJack F Vogel 			}
102513705f88SJack F Vogel 		}
102613705f88SJack F Vogel 	}
102713705f88SJack F Vogel 
102813705f88SJack F Vogel 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
102913705f88SJack F Vogel 
103013705f88SJack F Vogel 	return checksum;
103113705f88SJack F Vogel }
103213705f88SJack F Vogel 
103313705f88SJack F Vogel /**
103413705f88SJack F Vogel  *  ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
103513705f88SJack F Vogel  *  @hw: pointer to hardware structure
103613705f88SJack F Vogel  *  @checksum_val: calculated checksum
103713705f88SJack F Vogel  *
103813705f88SJack F Vogel  *  Performs checksum calculation and validates the EEPROM checksum.  If the
103913705f88SJack F Vogel  *  caller does not need checksum_val, the value can be NULL.
104013705f88SJack F Vogel  **/
104113705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
104213705f88SJack F Vogel 					   u16 *checksum_val)
104313705f88SJack F Vogel {
104413705f88SJack F Vogel 	s32 status;
104513705f88SJack F Vogel 	u16 checksum;
104613705f88SJack F Vogel 	u16 read_checksum = 0;
104713705f88SJack F Vogel 
104813705f88SJack F Vogel 	/*
104913705f88SJack F Vogel 	 * Read the first word from the EEPROM. If this times out or fails, do
105013705f88SJack F Vogel 	 * not continue or we could be in for a very long wait while every
105113705f88SJack F Vogel 	 * EEPROM read fails
105213705f88SJack F Vogel 	 */
105313705f88SJack F Vogel 	status = ixgbe_read_eeprom(hw, 0, &checksum);
105413705f88SJack F Vogel 
105513705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
105613705f88SJack F Vogel 		checksum = ixgbe_calc_eeprom_checksum(hw);
105713705f88SJack F Vogel 
105813705f88SJack F Vogel 		ixgbe_read_eeprom(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
105913705f88SJack F Vogel 
106013705f88SJack F Vogel 		/*
106113705f88SJack F Vogel 		 * Verify read checksum from EEPROM is the same as
106213705f88SJack F Vogel 		 * calculated checksum
106313705f88SJack F Vogel 		 */
106413705f88SJack F Vogel 		if (read_checksum != checksum) {
106513705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM_CHECKSUM;
106613705f88SJack F Vogel 		}
106713705f88SJack F Vogel 
106813705f88SJack F Vogel 		/* If the user cares, return the calculated checksum */
106913705f88SJack F Vogel 		if (checksum_val) {
107013705f88SJack F Vogel 			*checksum_val = checksum;
107113705f88SJack F Vogel 		}
107213705f88SJack F Vogel 	} else {
107313705f88SJack F Vogel 		DEBUGOUT("EEPROM read failed\n");
107413705f88SJack F Vogel 	}
107513705f88SJack F Vogel 
107613705f88SJack F Vogel 	return status;
107713705f88SJack F Vogel }
107813705f88SJack F Vogel 
107913705f88SJack F Vogel /**
108013705f88SJack F Vogel  *  ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksm
108113705f88SJack F Vogel  *  @hw: pointer to hardware structure
108213705f88SJack F Vogel  **/
108313705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
108413705f88SJack F Vogel {
108513705f88SJack F Vogel 	s32 status;
108613705f88SJack F Vogel 	u16 checksum;
108713705f88SJack F Vogel 
108813705f88SJack F Vogel 	/*
108913705f88SJack F Vogel 	 * Read the first word from the EEPROM. If this times out or fails, do
109013705f88SJack F Vogel 	 * not continue or we could be in for a very long wait while every
109113705f88SJack F Vogel 	 * EEPROM read fails
109213705f88SJack F Vogel 	 */
109313705f88SJack F Vogel 	status = ixgbe_read_eeprom(hw, 0, &checksum);
109413705f88SJack F Vogel 
109513705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
109613705f88SJack F Vogel 		checksum = ixgbe_calc_eeprom_checksum(hw);
109713705f88SJack F Vogel 		status = ixgbe_write_eeprom(hw, IXGBE_EEPROM_CHECKSUM,
109813705f88SJack F Vogel 					    checksum);
109913705f88SJack F Vogel 	} else {
110013705f88SJack F Vogel 		DEBUGOUT("EEPROM read failed\n");
110113705f88SJack F Vogel 	}
110213705f88SJack F Vogel 
110313705f88SJack F Vogel 	return status;
110413705f88SJack F Vogel }
110513705f88SJack F Vogel 
110613705f88SJack F Vogel /**
110713705f88SJack F Vogel  *  ixgbe_validate_mac_addr - Validate MAC address
110813705f88SJack F Vogel  *  @mac_addr: pointer to MAC address.
110913705f88SJack F Vogel  *
111013705f88SJack F Vogel  *  Tests a MAC address to ensure it is a valid Individual Address
111113705f88SJack F Vogel  **/
111213705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr)
111313705f88SJack F Vogel {
111413705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
111513705f88SJack F Vogel 
111613705f88SJack F Vogel 	/* Make sure it is not a multicast address */
111713705f88SJack F Vogel 	if (IXGBE_IS_MULTICAST(mac_addr)) {
111813705f88SJack F Vogel 		DEBUGOUT("MAC address is multicast\n");
111913705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
112013705f88SJack F Vogel 	/* Not a broadcast address */
112113705f88SJack F Vogel 	} else if (IXGBE_IS_BROADCAST(mac_addr)) {
112213705f88SJack F Vogel 		DEBUGOUT("MAC address is broadcast\n");
112313705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
112413705f88SJack F Vogel 	/* Reject the zero address */
112513705f88SJack F Vogel 	} else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
112613705f88SJack F Vogel 		 mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
112713705f88SJack F Vogel 		DEBUGOUT("MAC address is all zeros\n");
112813705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
112913705f88SJack F Vogel 	}
113013705f88SJack F Vogel 	return status;
113113705f88SJack F Vogel }
113213705f88SJack F Vogel 
113313705f88SJack F Vogel /**
113413705f88SJack F Vogel  *  ixgbe_set_rar_generic - Set RX address register
113513705f88SJack F Vogel  *  @hw: pointer to hardware structure
113613705f88SJack F Vogel  *  @addr: Address to put into receive address register
113713705f88SJack F Vogel  *  @index: Receive address register to write
113813705f88SJack F Vogel  *  @vind: Vind to set RAR to
113913705f88SJack F Vogel  *  @enable_addr: set flag that address is active
114013705f88SJack F Vogel  *
114113705f88SJack F Vogel  *  Puts an ethernet address into a receive address register.
114213705f88SJack F Vogel  **/
114313705f88SJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vind,
114413705f88SJack F Vogel 			  u32 enable_addr)
114513705f88SJack F Vogel {
114613705f88SJack F Vogel 	u32 rar_low, rar_high;
114713705f88SJack F Vogel 
114813705f88SJack F Vogel 	/*
114913705f88SJack F Vogel 	 * HW expects these in little endian so we reverse the byte order from
115013705f88SJack F Vogel 	 * network order (big endian) to little endian
115113705f88SJack F Vogel 	 */
115213705f88SJack F Vogel 	rar_low = ((u32)addr[0] |
115313705f88SJack F Vogel 		   ((u32)addr[1] << 8) |
115413705f88SJack F Vogel 		   ((u32)addr[2] << 16) |
115513705f88SJack F Vogel 		   ((u32)addr[3] << 24));
115613705f88SJack F Vogel 
115713705f88SJack F Vogel 	rar_high = ((u32)addr[4] |
115813705f88SJack F Vogel 		    ((u32)addr[5] << 8) |
115913705f88SJack F Vogel 		    ((vind << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK));
116013705f88SJack F Vogel 
116113705f88SJack F Vogel 	if (enable_addr != 0)
116213705f88SJack F Vogel 		rar_high |= IXGBE_RAH_AV;
116313705f88SJack F Vogel 
116413705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
116513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
116613705f88SJack F Vogel 
116713705f88SJack F Vogel 	return IXGBE_SUCCESS;
116813705f88SJack F Vogel }
116913705f88SJack F Vogel 
117013705f88SJack F Vogel /**
117113705f88SJack F Vogel  *  ixgbe_enable_rar - Enable RX address register
117213705f88SJack F Vogel  *  @hw: pointer to hardware structure
117313705f88SJack F Vogel  *  @index: index into the RAR table
117413705f88SJack F Vogel  *
117513705f88SJack F Vogel  *  Enables the select receive address register.
117613705f88SJack F Vogel  **/
117713705f88SJack F Vogel static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index)
117813705f88SJack F Vogel {
117913705f88SJack F Vogel 	u32 rar_high;
118013705f88SJack F Vogel 
118113705f88SJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
118213705f88SJack F Vogel 	rar_high |= IXGBE_RAH_AV;
118313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
118413705f88SJack F Vogel }
118513705f88SJack F Vogel 
118613705f88SJack F Vogel /**
118713705f88SJack F Vogel  *  ixgbe_disable_rar - Disable RX address register
118813705f88SJack F Vogel  *  @hw: pointer to hardware structure
118913705f88SJack F Vogel  *  @index: index into the RAR table
119013705f88SJack F Vogel  *
119113705f88SJack F Vogel  *  Disables the select receive address register.
119213705f88SJack F Vogel  **/
119313705f88SJack F Vogel static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index)
119413705f88SJack F Vogel {
119513705f88SJack F Vogel 	u32 rar_high;
119613705f88SJack F Vogel 
119713705f88SJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
119813705f88SJack F Vogel 	rar_high &= (~IXGBE_RAH_AV);
119913705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
120013705f88SJack F Vogel }
120113705f88SJack F Vogel 
120213705f88SJack F Vogel /**
120313705f88SJack F Vogel  *  ixgbe_init_rx_addrs_generic - Initializes receive address filters.
120413705f88SJack F Vogel  *  @hw: pointer to hardware structure
120513705f88SJack F Vogel  *
120613705f88SJack F Vogel  *  Places the MAC address in receive address register 0 and clears the rest
120713705f88SJack F Vogel  *  of the receive addresss registers. Clears the multicast table. Assumes
120813705f88SJack F Vogel  *  the receiver is in reset when the routine is called.
120913705f88SJack F Vogel  **/
121013705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
121113705f88SJack F Vogel {
121213705f88SJack F Vogel 	u32 i;
121313705f88SJack F Vogel 	u32 rar_entries = ixgbe_get_num_rx_addrs(hw);
121413705f88SJack F Vogel 
121513705f88SJack F Vogel 	/*
121613705f88SJack F Vogel 	 * If the current mac address is valid, assume it is a software override
121713705f88SJack F Vogel 	 * to the permanent address.
121813705f88SJack F Vogel 	 * Otherwise, use the permanent address from the eeprom.
121913705f88SJack F Vogel 	 */
122013705f88SJack F Vogel 	if (ixgbe_validate_mac_addr(hw->mac.addr) ==
122113705f88SJack F Vogel 	    IXGBE_ERR_INVALID_MAC_ADDR) {
122213705f88SJack F Vogel 		/* Get the MAC address from the RAR0 for later reference */
122313705f88SJack F Vogel 		ixgbe_get_mac_addr(hw, hw->mac.addr);
122413705f88SJack F Vogel 
122513705f88SJack F Vogel 		DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
122613705f88SJack F Vogel 			  hw->mac.addr[0], hw->mac.addr[1],
122713705f88SJack F Vogel 			  hw->mac.addr[2]);
122813705f88SJack F Vogel 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
122913705f88SJack F Vogel 			  hw->mac.addr[4], hw->mac.addr[5]);
123013705f88SJack F Vogel 	} else {
123113705f88SJack F Vogel 		/* Setup the receive address. */
123213705f88SJack F Vogel 		DEBUGOUT("Overriding MAC Address in RAR[0]\n");
123313705f88SJack F Vogel 		DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
123413705f88SJack F Vogel 			  hw->mac.addr[0], hw->mac.addr[1],
123513705f88SJack F Vogel 			  hw->mac.addr[2]);
123613705f88SJack F Vogel 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
123713705f88SJack F Vogel 			  hw->mac.addr[4], hw->mac.addr[5]);
123813705f88SJack F Vogel 
123913705f88SJack F Vogel 		ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
124013705f88SJack F Vogel 	}
124113705f88SJack F Vogel 
124213705f88SJack F Vogel 	hw->addr_ctrl.rar_used_count = 1;
124313705f88SJack F Vogel 
124413705f88SJack F Vogel 	/* Zero out the other receive addresses. */
124513705f88SJack F Vogel 	DEBUGOUT("Clearing RAR[1-15]\n");
124613705f88SJack F Vogel 	for (i = 1; i < rar_entries; i++) {
124713705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
124813705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
124913705f88SJack F Vogel 	}
125013705f88SJack F Vogel 
125113705f88SJack F Vogel 	/* Clear the MTA */
125213705f88SJack F Vogel 	hw->addr_ctrl.mc_addr_in_rar_count = 0;
125313705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use = 0;
125413705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
125513705f88SJack F Vogel 
125613705f88SJack F Vogel 	DEBUGOUT(" Clearing MTA\n");
125713705f88SJack F Vogel 	for (i = 0; i < IXGBE_MC_TBL_SIZE; i++)
125813705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
125913705f88SJack F Vogel 
126013705f88SJack F Vogel 	return IXGBE_SUCCESS;
126113705f88SJack F Vogel }
126213705f88SJack F Vogel 
126313705f88SJack F Vogel /**
126413705f88SJack F Vogel  *  ixgbe_mta_vector - Determines bit-vector in multicast table to set
126513705f88SJack F Vogel  *  @hw: pointer to hardware structure
126613705f88SJack F Vogel  *  @mc_addr: the multicast address
126713705f88SJack F Vogel  *
126813705f88SJack F Vogel  *  Extracts the 12 bits, from a multicast address, to determine which
126913705f88SJack F Vogel  *  bit-vector to set in the multicast table. The hardware uses 12 bits, from
127013705f88SJack F Vogel  *  incoming rx multicast addresses, to determine the bit-vector to check in
127113705f88SJack F Vogel  *  the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
127213705f88SJack F Vogel  *  by the MO field of the MCSTCTRL. The MO field is set during initalization
127313705f88SJack F Vogel  *  to mc_filter_type.
127413705f88SJack F Vogel  **/
127513705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
127613705f88SJack F Vogel {
127713705f88SJack F Vogel 	u32 vector = 0;
127813705f88SJack F Vogel 
127913705f88SJack F Vogel 	switch (hw->mac.mc_filter_type) {
128013705f88SJack F Vogel 	case 0:	  /* use bits [47:36] of the address */
128113705f88SJack F Vogel 		vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
128213705f88SJack F Vogel 		break;
128313705f88SJack F Vogel 	case 1:	  /* use bits [46:35] of the address */
128413705f88SJack F Vogel 		vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
128513705f88SJack F Vogel 		break;
128613705f88SJack F Vogel 	case 2:	  /* use bits [45:34] of the address */
128713705f88SJack F Vogel 		vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
128813705f88SJack F Vogel 		break;
128913705f88SJack F Vogel 	case 3:	  /* use bits [43:32] of the address */
129013705f88SJack F Vogel 		vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
129113705f88SJack F Vogel 		break;
129213705f88SJack F Vogel 	default:	 /* Invalid mc_filter_type */
129313705f88SJack F Vogel 		DEBUGOUT("MC filter type param set incorrectly\n");
129413705f88SJack F Vogel 		ASSERT(0);
129513705f88SJack F Vogel 		break;
129613705f88SJack F Vogel 	}
129713705f88SJack F Vogel 
129813705f88SJack F Vogel 	/* vector can only be 12-bits or boundary will be exceeded */
129913705f88SJack F Vogel 	vector &= 0xFFF;
130013705f88SJack F Vogel 	return vector;
130113705f88SJack F Vogel }
130213705f88SJack F Vogel 
130313705f88SJack F Vogel /**
130413705f88SJack F Vogel  *  ixgbe_set_mta - Set bit-vector in multicast table
130513705f88SJack F Vogel  *  @hw: pointer to hardware structure
130613705f88SJack F Vogel  *  @hash_value: Multicast address hash value
130713705f88SJack F Vogel  *
130813705f88SJack F Vogel  *  Sets the bit-vector in the multicast table.
130913705f88SJack F Vogel  **/
131013705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
131113705f88SJack F Vogel {
131213705f88SJack F Vogel 	u32 vector;
131313705f88SJack F Vogel 	u32 vector_bit;
131413705f88SJack F Vogel 	u32 vector_reg;
131513705f88SJack F Vogel 	u32 mta_reg;
131613705f88SJack F Vogel 
131713705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use++;
131813705f88SJack F Vogel 
131913705f88SJack F Vogel 	vector = ixgbe_mta_vector(hw, mc_addr);
132013705f88SJack F Vogel 	DEBUGOUT1(" bit-vector = 0x%03X\n", vector);
132113705f88SJack F Vogel 
132213705f88SJack F Vogel 	/*
132313705f88SJack F Vogel 	 * The MTA is a register array of 128 32-bit registers. It is treated
132413705f88SJack F Vogel 	 * like an array of 4096 bits.  We want to set bit
132513705f88SJack F Vogel 	 * BitArray[vector_value]. So we figure out what register the bit is
132613705f88SJack F Vogel 	 * in, read it, OR in the new bit, then write back the new value.  The
132713705f88SJack F Vogel 	 * register is determined by the upper 7 bits of the vector value and
132813705f88SJack F Vogel 	 * the bit within that register are determined by the lower 5 bits of
132913705f88SJack F Vogel 	 * the value.
133013705f88SJack F Vogel 	 */
133113705f88SJack F Vogel 	vector_reg = (vector >> 5) & 0x7F;
133213705f88SJack F Vogel 	vector_bit = vector & 0x1F;
133313705f88SJack F Vogel 	mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg));
133413705f88SJack F Vogel 	mta_reg |= (1 << vector_bit);
133513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
133613705f88SJack F Vogel }
133713705f88SJack F Vogel 
133813705f88SJack F Vogel /**
133913705f88SJack F Vogel  *  ixgbe_add_mc_addr - Adds a multicast address.
134013705f88SJack F Vogel  *  @hw: pointer to hardware structure
134113705f88SJack F Vogel  *  @mc_addr: new multicast address
134213705f88SJack F Vogel  *
134313705f88SJack F Vogel  *  Adds it to unused receive address register or to the multicast table.
134413705f88SJack F Vogel  **/
134513705f88SJack F Vogel void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr)
134613705f88SJack F Vogel {
134713705f88SJack F Vogel 	u32 rar_entries = ixgbe_get_num_rx_addrs(hw);
134813705f88SJack F Vogel 
134913705f88SJack F Vogel 	DEBUGOUT6(" MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n",
135013705f88SJack F Vogel 		  mc_addr[0], mc_addr[1], mc_addr[2],
135113705f88SJack F Vogel 		  mc_addr[3], mc_addr[4], mc_addr[5]);
135213705f88SJack F Vogel 
135313705f88SJack F Vogel 	/*
135413705f88SJack F Vogel 	 * Place this multicast address in the RAR if there is room,
135513705f88SJack F Vogel 	 * else put it in the MTA
135613705f88SJack F Vogel 	 */
135713705f88SJack F Vogel 	if (hw->addr_ctrl.rar_used_count < rar_entries) {
135813705f88SJack F Vogel 		ixgbe_set_rar(hw, hw->addr_ctrl.rar_used_count,
135913705f88SJack F Vogel 			      mc_addr, 0, IXGBE_RAH_AV);
136013705f88SJack F Vogel 		DEBUGOUT1("Added a multicast address to RAR[%d]\n",
136113705f88SJack F Vogel 			  hw->addr_ctrl.rar_used_count);
136213705f88SJack F Vogel 		hw->addr_ctrl.rar_used_count++;
136313705f88SJack F Vogel 		hw->addr_ctrl.mc_addr_in_rar_count++;
136413705f88SJack F Vogel 	} else {
136513705f88SJack F Vogel 		ixgbe_set_mta(hw, mc_addr);
136613705f88SJack F Vogel 	}
136713705f88SJack F Vogel 
136813705f88SJack F Vogel 	DEBUGOUT("ixgbe_add_mc_addr Complete\n");
136913705f88SJack F Vogel }
137013705f88SJack F Vogel 
137113705f88SJack F Vogel /**
137213705f88SJack F Vogel  *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
137313705f88SJack F Vogel  *  @hw: pointer to hardware structure
137413705f88SJack F Vogel  *  @mc_addr_list: the list of new multicast addresses
137513705f88SJack F Vogel  *  @mc_addr_count: number of addresses
137613705f88SJack F Vogel  *  @pad: number of bytes between addresses in the list
137713705f88SJack F Vogel  *
137813705f88SJack F Vogel  *  The given list replaces any existing list. Clears the MC addrs from receive
137913705f88SJack F Vogel  *  address registers and the multicast table. Uses unsed receive address
138013705f88SJack F Vogel  *  registers for the first multicast addresses, and hashes the rest into the
138113705f88SJack F Vogel  *  multicast table.
138213705f88SJack F Vogel  **/
138313705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
138413705f88SJack F Vogel 				      u32 mc_addr_count, u32 pad)
138513705f88SJack F Vogel {
138613705f88SJack F Vogel 	u32 i;
138713705f88SJack F Vogel 	u32 rar_entries = ixgbe_get_num_rx_addrs(hw);
138813705f88SJack F Vogel 
138913705f88SJack F Vogel 	/*
139013705f88SJack F Vogel 	 * Set the new number of MC addresses that we are being requested to
139113705f88SJack F Vogel 	 * use.
139213705f88SJack F Vogel 	 */
139313705f88SJack F Vogel 	hw->addr_ctrl.num_mc_addrs = mc_addr_count;
139413705f88SJack F Vogel 	hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count;
139513705f88SJack F Vogel 	hw->addr_ctrl.mc_addr_in_rar_count = 0;
139613705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use = 0;
139713705f88SJack F Vogel 
139813705f88SJack F Vogel 	/* Zero out the other receive addresses. */
139913705f88SJack F Vogel 	DEBUGOUT("Clearing RAR[1-15]\n");
140013705f88SJack F Vogel 	for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) {
140113705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
140213705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
140313705f88SJack F Vogel 	}
140413705f88SJack F Vogel 
140513705f88SJack F Vogel 	/* Clear the MTA */
140613705f88SJack F Vogel 	DEBUGOUT(" Clearing MTA\n");
140713705f88SJack F Vogel 	for (i = 0; i < IXGBE_MC_TBL_SIZE; i++)
140813705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
140913705f88SJack F Vogel 
141013705f88SJack F Vogel 	/* Add the new addresses */
141113705f88SJack F Vogel 	for (i = 0; i < mc_addr_count; i++) {
141213705f88SJack F Vogel 		DEBUGOUT(" Adding the multicast addresses:\n");
141313705f88SJack F Vogel 		ixgbe_add_mc_addr(hw, mc_addr_list +
141413705f88SJack F Vogel 				  (i * (IXGBE_ETH_LENGTH_OF_ADDRESS + pad)));
141513705f88SJack F Vogel 	}
141613705f88SJack F Vogel 
141713705f88SJack F Vogel 	/* Enable mta */
141813705f88SJack F Vogel 	if (hw->addr_ctrl.mta_in_use > 0)
141913705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
142013705f88SJack F Vogel 				IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
142113705f88SJack F Vogel 
142213705f88SJack F Vogel 	DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n");
142313705f88SJack F Vogel 	return IXGBE_SUCCESS;
142413705f88SJack F Vogel }
142513705f88SJack F Vogel 
142613705f88SJack F Vogel /**
142713705f88SJack F Vogel  *  ixgbe_enable_mc_generic - Enable multicast address in RAR
142813705f88SJack F Vogel  *  @hw: pointer to hardware structure
142913705f88SJack F Vogel  *
143013705f88SJack F Vogel  *  Enables multicast address in RAR and the use of the multicast hash table.
143113705f88SJack F Vogel  **/
143213705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
143313705f88SJack F Vogel {
143413705f88SJack F Vogel 	u32 i;
143513705f88SJack F Vogel 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
143613705f88SJack F Vogel 
143713705f88SJack F Vogel 	if (a->mc_addr_in_rar_count > 0)
143813705f88SJack F Vogel 		for (i = (a->rar_used_count - a->mc_addr_in_rar_count);
143913705f88SJack F Vogel 		     i < a->rar_used_count; i++)
144013705f88SJack F Vogel 			ixgbe_enable_rar(hw, i);
144113705f88SJack F Vogel 
144213705f88SJack F Vogel 	if (a->mta_in_use > 0)
144313705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
144413705f88SJack F Vogel 				hw->mac.mc_filter_type);
144513705f88SJack F Vogel 
144613705f88SJack F Vogel 	return IXGBE_SUCCESS;
144713705f88SJack F Vogel }
144813705f88SJack F Vogel 
144913705f88SJack F Vogel /**
145013705f88SJack F Vogel  *  ixgbe_disable_mc_generic - Disable mutlicast address in RAR
145113705f88SJack F Vogel  *  @hw: pointer to hardware structure
145213705f88SJack F Vogel  *
145313705f88SJack F Vogel  *  Disables multicast address in RAR and the use of the multicast hash table.
145413705f88SJack F Vogel  **/
145513705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
145613705f88SJack F Vogel {
145713705f88SJack F Vogel 	u32 i;
145813705f88SJack F Vogel 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
145913705f88SJack F Vogel 
146013705f88SJack F Vogel 	if (a->mc_addr_in_rar_count > 0)
146113705f88SJack F Vogel 		for (i = (a->rar_used_count - a->mc_addr_in_rar_count);
146213705f88SJack F Vogel 		     i < a->rar_used_count; i++)
146313705f88SJack F Vogel 			ixgbe_disable_rar(hw, i);
146413705f88SJack F Vogel 
146513705f88SJack F Vogel 	if (a->mta_in_use > 0)
146613705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
146713705f88SJack F Vogel 
146813705f88SJack F Vogel 	return IXGBE_SUCCESS;
146913705f88SJack F Vogel }
147013705f88SJack F Vogel 
147113705f88SJack F Vogel /**
147213705f88SJack F Vogel  *  ixgbe_clear_vfta_generic - Clear VLAN filter table
147313705f88SJack F Vogel  *  @hw: pointer to hardware structure
147413705f88SJack F Vogel  *
147513705f88SJack F Vogel  *  Clears the VLAN filer table, and the VMDq index associated with the filter
147613705f88SJack F Vogel  **/
147713705f88SJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
147813705f88SJack F Vogel {
147913705f88SJack F Vogel 	u32 offset;
148013705f88SJack F Vogel 	u32 vlanbyte;
148113705f88SJack F Vogel 
148213705f88SJack F Vogel 	for (offset = 0; offset < IXGBE_VLAN_FILTER_TBL_SIZE; offset++)
148313705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
148413705f88SJack F Vogel 
148513705f88SJack F Vogel 	for (vlanbyte = 0; vlanbyte < 4; vlanbyte++)
148613705f88SJack F Vogel 		for (offset = 0; offset < IXGBE_VLAN_FILTER_TBL_SIZE; offset++)
148713705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset),
148813705f88SJack F Vogel 					0);
148913705f88SJack F Vogel 
149013705f88SJack F Vogel 	return IXGBE_SUCCESS;
149113705f88SJack F Vogel }
149213705f88SJack F Vogel 
149313705f88SJack F Vogel /**
149413705f88SJack F Vogel  *  ixgbe_set_vfta_generic - Set VLAN filter table
149513705f88SJack F Vogel  *  @hw: pointer to hardware structure
149613705f88SJack F Vogel  *  @vlan: VLAN id to write to VLAN filter
149713705f88SJack F Vogel  *  @vind: VMDq output index that maps queue to VLAN id in VFTA
149813705f88SJack F Vogel  *  @vlan_on: boolean flag to turn on/off VLAN in VFTA
149913705f88SJack F Vogel  *
150013705f88SJack F Vogel  *  Turn on/off specified VLAN in the VLAN filter table.
150113705f88SJack F Vogel  **/
150213705f88SJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
150313705f88SJack F Vogel 			   bool vlan_on)
150413705f88SJack F Vogel {
150513705f88SJack F Vogel 	u32 VftaIndex;
150613705f88SJack F Vogel 	u32 BitOffset;
150713705f88SJack F Vogel 	u32 VftaReg;
150813705f88SJack F Vogel 	u32 VftaByte;
150913705f88SJack F Vogel 
151013705f88SJack F Vogel 	/* Determine 32-bit word position in array */
151113705f88SJack F Vogel 	VftaIndex = (vlan >> 5) & 0x7F;   /* upper seven bits */
151213705f88SJack F Vogel 
151313705f88SJack F Vogel 	/* Determine the location of the (VMD) queue index */
151413705f88SJack F Vogel 	VftaByte =  ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */
151513705f88SJack F Vogel 	BitOffset = (vlan & 0x7) << 2;    /* lower 3 bits indicate nibble */
151613705f88SJack F Vogel 
151713705f88SJack F Vogel 	/* Set the nibble for VMD queue index */
151813705f88SJack F Vogel 	VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex));
151913705f88SJack F Vogel 	VftaReg &= (~(0x0F << BitOffset));
152013705f88SJack F Vogel 	VftaReg |= (vind << BitOffset);
152113705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex), VftaReg);
152213705f88SJack F Vogel 
152313705f88SJack F Vogel 	/* Determine the location of the bit for this VLAN id */
152413705f88SJack F Vogel 	BitOffset = vlan & 0x1F;	   /* lower five bits */
152513705f88SJack F Vogel 
152613705f88SJack F Vogel 	VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTA(VftaIndex));
152713705f88SJack F Vogel 	if (vlan_on)
152813705f88SJack F Vogel 		/* Turn on this VLAN id */
152913705f88SJack F Vogel 		VftaReg |= (1 << BitOffset);
153013705f88SJack F Vogel 	else
153113705f88SJack F Vogel 		/* Turn off this VLAN id */
153213705f88SJack F Vogel 		VftaReg &= ~(1 << BitOffset);
153313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_VFTA(VftaIndex), VftaReg);
153413705f88SJack F Vogel 
153513705f88SJack F Vogel 	return IXGBE_SUCCESS;
153613705f88SJack F Vogel }
153713705f88SJack F Vogel 
153813705f88SJack F Vogel /**
153913705f88SJack F Vogel  *  ixgbe_setup_fc_generic - Configure flow control settings
154013705f88SJack F Vogel  *  @hw: pointer to hardware structure
154113705f88SJack F Vogel  *  @packetbuf_num: packet buffer number (0-7)
154213705f88SJack F Vogel  *
154313705f88SJack F Vogel  *  Configures the flow control settings based on SW configuration.
154413705f88SJack F Vogel  *  This function is used for 802.3x flow control configuration only.
154513705f88SJack F Vogel  **/
154613705f88SJack F Vogel s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
154713705f88SJack F Vogel {
154813705f88SJack F Vogel 	u32 frctl_reg;
154913705f88SJack F Vogel 	u32 rmcs_reg;
155013705f88SJack F Vogel 
155113705f88SJack F Vogel 	if (packetbuf_num < 0 || packetbuf_num > 7) {
155213705f88SJack F Vogel 		DEBUGOUT1("Invalid packet buffer number [%d], expected range is"
155313705f88SJack F Vogel 			  " 0-7\n", packetbuf_num);
155413705f88SJack F Vogel 		ASSERT(0);
155513705f88SJack F Vogel 	}
155613705f88SJack F Vogel 
155713705f88SJack F Vogel 	frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
155813705f88SJack F Vogel 	frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
155913705f88SJack F Vogel 
156013705f88SJack F Vogel 	rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
156113705f88SJack F Vogel 	rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X);
156213705f88SJack F Vogel 
156313705f88SJack F Vogel 	/*
156413705f88SJack F Vogel 	 * We want to save off the original Flow Control configuration just in
156513705f88SJack F Vogel 	 * case we get disconnected and then reconnected into a different hub
156613705f88SJack F Vogel 	 * or switch with different Flow Control capabilities.
156713705f88SJack F Vogel 	 */
156813705f88SJack F Vogel 	hw->fc.type = hw->fc.original_type;
156913705f88SJack F Vogel 
157013705f88SJack F Vogel 	/*
157113705f88SJack F Vogel 	 * The possible values of the "flow_control" parameter are:
157213705f88SJack F Vogel 	 * 0: Flow control is completely disabled
157313705f88SJack F Vogel 	 * 1: Rx flow control is enabled (we can receive pause frames but not
157413705f88SJack F Vogel 	 *    send pause frames).
157513705f88SJack F Vogel 	 * 2: Tx flow control is enabled (we can send pause frames but we do not
157613705f88SJack F Vogel 	 *    support receiving pause frames)
157713705f88SJack F Vogel 	 * 3: Both Rx and TX flow control (symmetric) are enabled.
157813705f88SJack F Vogel 	 * other: Invalid.
157913705f88SJack F Vogel 	 */
158013705f88SJack F Vogel 	switch (hw->fc.type) {
158113705f88SJack F Vogel 	case ixgbe_fc_none:
158213705f88SJack F Vogel 		break;
158313705f88SJack F Vogel 	case ixgbe_fc_rx_pause:
158413705f88SJack F Vogel 		/*
158513705f88SJack F Vogel 		 * RX Flow control is enabled,
158613705f88SJack F Vogel 		 * and TX Flow control is disabled.
158713705f88SJack F Vogel 		 */
158813705f88SJack F Vogel 		frctl_reg |= IXGBE_FCTRL_RFCE;
158913705f88SJack F Vogel 		break;
159013705f88SJack F Vogel 	case ixgbe_fc_tx_pause:
159113705f88SJack F Vogel 		/*
159213705f88SJack F Vogel 		 * TX Flow control is enabled, and RX Flow control is disabled,
159313705f88SJack F Vogel 		 * by a software over-ride.
159413705f88SJack F Vogel 		 */
159513705f88SJack F Vogel 		rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
159613705f88SJack F Vogel 		break;
159713705f88SJack F Vogel 	case ixgbe_fc_full:
159813705f88SJack F Vogel 		/*
159913705f88SJack F Vogel 		 * Flow control (both RX and TX) is enabled by a software
160013705f88SJack F Vogel 		 * over-ride.
160113705f88SJack F Vogel 		 */
160213705f88SJack F Vogel 		frctl_reg |= IXGBE_FCTRL_RFCE;
160313705f88SJack F Vogel 		rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
160413705f88SJack F Vogel 		break;
160513705f88SJack F Vogel 	default:
160613705f88SJack F Vogel 		/* We should never get here.  The value should be 0-3. */
160713705f88SJack F Vogel 		DEBUGOUT("Flow control param set incorrectly\n");
160813705f88SJack F Vogel 		ASSERT(0);
160913705f88SJack F Vogel 		break;
161013705f88SJack F Vogel 	}
161113705f88SJack F Vogel 
161213705f88SJack F Vogel 	/* Enable 802.3x based flow control settings. */
161313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg);
161413705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
161513705f88SJack F Vogel 
161613705f88SJack F Vogel 	/*
161713705f88SJack F Vogel 	 * We need to set up the Receive Threshold high and low water
161813705f88SJack F Vogel 	 * marks as well as (optionally) enabling the transmission of
161913705f88SJack F Vogel 	 * XON frames.
162013705f88SJack F Vogel 	 */
162113705f88SJack F Vogel 	if (hw->fc.type & ixgbe_fc_tx_pause) {
162213705f88SJack F Vogel 		if (hw->fc.send_xon) {
162313705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
162413705f88SJack F Vogel 					(hw->fc.low_water | IXGBE_FCRTL_XONE));
162513705f88SJack F Vogel 		} else {
162613705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
162713705f88SJack F Vogel 					hw->fc.low_water);
162813705f88SJack F Vogel 		}
162913705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num),
163013705f88SJack F Vogel 				(hw->fc.high_water)|IXGBE_FCRTH_FCEN);
163113705f88SJack F Vogel 	}
163213705f88SJack F Vogel 
163313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time);
163413705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
163513705f88SJack F Vogel 
163613705f88SJack F Vogel 	return IXGBE_SUCCESS;
163713705f88SJack F Vogel }
163813705f88SJack F Vogel 
163913705f88SJack F Vogel /**
164013705f88SJack F Vogel  *  ixgbe_disable_pcie_master - Disable PCI-express master access
164113705f88SJack F Vogel  *  @hw: pointer to hardware structure
164213705f88SJack F Vogel  *
164313705f88SJack F Vogel  *  Disables PCI-Express master access and verifies there are no pending
164413705f88SJack F Vogel  *  requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
164513705f88SJack F Vogel  *  bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS
164613705f88SJack F Vogel  *  is returned signifying master requests disabled.
164713705f88SJack F Vogel  **/
164813705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
164913705f88SJack F Vogel {
165013705f88SJack F Vogel 	u32 ctrl;
165113705f88SJack F Vogel 	s32 i;
165213705f88SJack F Vogel 	s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
165313705f88SJack F Vogel 
165413705f88SJack F Vogel 	ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
165513705f88SJack F Vogel 	ctrl |= IXGBE_CTRL_GIO_DIS;
165613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
165713705f88SJack F Vogel 
165813705f88SJack F Vogel 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
165913705f88SJack F Vogel 		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) {
166013705f88SJack F Vogel 			status = IXGBE_SUCCESS;
166113705f88SJack F Vogel 			break;
166213705f88SJack F Vogel 		}
166313705f88SJack F Vogel 		usec_delay(100);
166413705f88SJack F Vogel 	}
166513705f88SJack F Vogel 
166613705f88SJack F Vogel 	return status;
166713705f88SJack F Vogel }
166813705f88SJack F Vogel 
166913705f88SJack F Vogel 
167013705f88SJack F Vogel /**
167113705f88SJack F Vogel  *  ixgbe_acquire_swfw_sync - Aquire SWFW semaphore
167213705f88SJack F Vogel  *  @hw: pointer to hardware structure
167313705f88SJack F Vogel  *  @mask: Mask to specify wich semaphore to acquire
167413705f88SJack F Vogel  *
167513705f88SJack F Vogel  *  Aquires the SWFW semaphore throught the GSSR register for the specified
167613705f88SJack F Vogel  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
167713705f88SJack F Vogel  **/
167813705f88SJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
167913705f88SJack F Vogel {
168013705f88SJack F Vogel 	u32 gssr;
168113705f88SJack F Vogel 	u32 swmask = mask;
168213705f88SJack F Vogel 	u32 fwmask = mask << 5;
168313705f88SJack F Vogel 	s32 timeout = 200;
168413705f88SJack F Vogel 
168513705f88SJack F Vogel 	while (timeout) {
168613705f88SJack F Vogel 		if (ixgbe_get_eeprom_semaphore(hw))
168713705f88SJack F Vogel 			return -IXGBE_ERR_SWFW_SYNC;
168813705f88SJack F Vogel 
168913705f88SJack F Vogel 		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
169013705f88SJack F Vogel 		if (!(gssr & (fwmask | swmask)))
169113705f88SJack F Vogel 			break;
169213705f88SJack F Vogel 
169313705f88SJack F Vogel 		/*
169413705f88SJack F Vogel 		 * Firmware currently using resource (fwmask) or other software
169513705f88SJack F Vogel 		 * thread currently using resource (swmask)
169613705f88SJack F Vogel 		 */
169713705f88SJack F Vogel 		ixgbe_release_eeprom_semaphore(hw);
169813705f88SJack F Vogel 		msec_delay(5);
169913705f88SJack F Vogel 		timeout--;
170013705f88SJack F Vogel 	}
170113705f88SJack F Vogel 
170213705f88SJack F Vogel 	if (!timeout) {
170313705f88SJack F Vogel 		DEBUGOUT("Driver can't access resource, GSSR timeout.\n");
170413705f88SJack F Vogel 		return -IXGBE_ERR_SWFW_SYNC;
170513705f88SJack F Vogel 	}
170613705f88SJack F Vogel 
170713705f88SJack F Vogel 	gssr |= swmask;
170813705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
170913705f88SJack F Vogel 
171013705f88SJack F Vogel 	ixgbe_release_eeprom_semaphore(hw);
171113705f88SJack F Vogel 	return IXGBE_SUCCESS;
171213705f88SJack F Vogel }
171313705f88SJack F Vogel 
171413705f88SJack F Vogel /**
171513705f88SJack F Vogel  *  ixgbe_release_swfw_sync - Release SWFW semaphore
171613705f88SJack F Vogel  *  @hw: pointer to hardware structure
171713705f88SJack F Vogel  *  @mask: Mask to specify wich semaphore to release
171813705f88SJack F Vogel  *
171913705f88SJack F Vogel  *  Releases the SWFW semaphore throught the GSSR register for the specified
172013705f88SJack F Vogel  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
172113705f88SJack F Vogel  **/
172213705f88SJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
172313705f88SJack F Vogel {
172413705f88SJack F Vogel 	u32 gssr;
172513705f88SJack F Vogel 	u32 swmask = mask;
172613705f88SJack F Vogel 
172713705f88SJack F Vogel 	ixgbe_get_eeprom_semaphore(hw);
172813705f88SJack F Vogel 
172913705f88SJack F Vogel 	gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
173013705f88SJack F Vogel 	gssr &= ~swmask;
173113705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
173213705f88SJack F Vogel 
173313705f88SJack F Vogel 	ixgbe_release_eeprom_semaphore(hw);
173413705f88SJack F Vogel }
173513705f88SJack F Vogel 
1736