2007-09-16 01:07:45 +04:00
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
2010-01-13 04:49:34 +03:00
Copyright ( c ) 1999 - 2010 Intel Corporation .
2007-09-16 01:07:45 +04:00
This program is free software ; you can redistribute it and / or modify it
under the terms and conditions of the GNU General Public License ,
version 2 , as published by the Free Software Foundation .
This program is distributed in the hope it will be useful , but WITHOUT
ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
more details .
You should have received a copy of the GNU General Public License along with
this program ; if not , write to the Free Software Foundation , Inc . ,
51 Franklin St - Fifth Floor , Boston , MA 02110 - 1301 USA .
The full GNU General Public License is included in this distribution in
the file called " COPYING " .
Contact Information :
e1000 - devel Mailing List < e1000 - devel @ lists . sourceforge . net >
Intel Corporation , 5200 N . E . Elam Young Parkway , Hillsboro , OR 97124 - 6497
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <linux/pci.h>
# include <linux/delay.h>
# include <linux/sched.h>
2009-05-23 03:22:17 +04:00
# include <linux/netdevice.h>
2007-09-16 01:07:45 +04:00
2009-02-27 18:44:30 +03:00
# include "ixgbe.h"
2007-09-16 01:07:45 +04:00
# include "ixgbe_common.h"
# include "ixgbe_phy.h"
2008-09-12 06:59:59 +04:00
static s32 ixgbe_acquire_eeprom ( struct ixgbe_hw * hw ) ;
2007-09-16 01:07:45 +04:00
static s32 ixgbe_get_eeprom_semaphore ( struct ixgbe_hw * hw ) ;
static void ixgbe_release_eeprom_semaphore ( struct ixgbe_hw * hw ) ;
2008-09-12 06:59:59 +04:00
static s32 ixgbe_ready_eeprom ( struct ixgbe_hw * hw ) ;
static void ixgbe_standby_eeprom ( struct ixgbe_hw * hw ) ;
static void ixgbe_shift_out_eeprom_bits ( struct ixgbe_hw * hw , u16 data ,
u16 count ) ;
static u16 ixgbe_shift_in_eeprom_bits ( struct ixgbe_hw * hw , u16 count ) ;
static void ixgbe_raise_eeprom_clk ( struct ixgbe_hw * hw , u32 * eec ) ;
static void ixgbe_lower_eeprom_clk ( struct ixgbe_hw * hw , u32 * eec ) ;
static void ixgbe_release_eeprom ( struct ixgbe_hw * hw ) ;
2007-09-16 01:07:45 +04:00
static u16 ixgbe_calc_eeprom_checksum ( struct ixgbe_hw * hw ) ;
2008-09-12 06:59:59 +04:00
static void ixgbe_enable_rar ( struct ixgbe_hw * hw , u32 index ) ;
static void ixgbe_disable_rar ( struct ixgbe_hw * hw , u32 index ) ;
2007-09-16 01:07:45 +04:00
static s32 ixgbe_mta_vector ( struct ixgbe_hw * hw , u8 * mc_addr ) ;
2008-09-12 06:59:59 +04:00
static void ixgbe_add_uc_addr ( struct ixgbe_hw * hw , u8 * addr , u32 vmdq ) ;
2009-08-25 08:47:32 +04:00
static s32 ixgbe_setup_fc ( struct ixgbe_hw * hw , s32 packetbuf_num ) ;
2007-09-16 01:07:45 +04:00
/**
2008-09-12 06:59:59 +04:00
* ixgbe_start_hw_generic - Prepare hardware for Tx / Rx
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
*
* Starts the hardware by filling the bus info structure and media type , clears
* all on chip counters , initializes receive address registers , multicast
* table , VLAN filter table , calls routine to set up link and flow control
* settings , and leaves transmit and receive units disabled and uninitialized
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_start_hw_generic ( struct ixgbe_hw * hw )
2007-09-16 01:07:45 +04:00
{
u32 ctrl_ext ;
/* Set the media type */
hw - > phy . media_type = hw - > mac . ops . get_media_type ( hw ) ;
/* Identify the PHY */
2008-09-12 06:59:59 +04:00
hw - > phy . ops . identify ( hw ) ;
2007-09-16 01:07:45 +04:00
/* Clear the VLAN filter table */
2008-09-12 06:59:59 +04:00
hw - > mac . ops . clear_vfta ( hw ) ;
2007-09-16 01:07:45 +04:00
/* Clear statistics registers */
2008-09-12 06:59:59 +04:00
hw - > mac . ops . clear_hw_cntrs ( hw ) ;
2007-09-16 01:07:45 +04:00
/* Set No Snoop Disable */
ctrl_ext = IXGBE_READ_REG ( hw , IXGBE_CTRL_EXT ) ;
ctrl_ext | = IXGBE_CTRL_EXT_NS_DIS ;
IXGBE_WRITE_REG ( hw , IXGBE_CTRL_EXT , ctrl_ext ) ;
2007-11-01 01:22:10 +03:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-16 01:07:45 +04:00
2009-06-04 15:11:13 +04:00
/* Setup flow control */
ixgbe_setup_fc ( hw , 0 ) ;
2007-09-16 01:07:45 +04:00
/* Clear adapter stopped flag */
hw - > adapter_stopped = false ;
return 0 ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_init_hw_generic - Generic hardware initialization
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
*
2008-09-12 06:59:59 +04:00
* Initialize the hardware by resetting the hardware , filling the bus info
2007-09-16 01:07:45 +04:00
* structure and media type , clears all on chip counters , initializes receive
* address registers , multicast table , VLAN filter table , calls routine to set
* up link and flow control settings , and leaves transmit and receive units
* disabled and uninitialized
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_init_hw_generic ( struct ixgbe_hw * hw )
2007-09-16 01:07:45 +04:00
{
2009-06-04 20:02:24 +04:00
s32 status ;
2007-09-16 01:07:45 +04:00
/* Reset the hardware */
2009-06-04 20:02:24 +04:00
status = hw - > mac . ops . reset_hw ( hw ) ;
2007-09-16 01:07:45 +04:00
2009-06-04 20:02:24 +04:00
if ( status = = 0 ) {
/* Start the HW */
status = hw - > mac . ops . start_hw ( hw ) ;
}
2007-09-16 01:07:45 +04:00
2009-06-04 20:02:24 +04:00
return status ;
2007-09-16 01:07:45 +04:00
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
*
* Clears all hardware statistics counters by reading them from the hardware
* Statistics counters are clear on read .
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_clear_hw_cntrs_generic ( struct ixgbe_hw * hw )
2007-09-16 01:07:45 +04:00
{
u16 i = 0 ;
IXGBE_READ_REG ( hw , IXGBE_CRCERRS ) ;
IXGBE_READ_REG ( hw , IXGBE_ILLERRC ) ;
IXGBE_READ_REG ( hw , IXGBE_ERRBC ) ;
IXGBE_READ_REG ( hw , IXGBE_MSPDC ) ;
for ( i = 0 ; i < 8 ; i + + )
IXGBE_READ_REG ( hw , IXGBE_MPC ( i ) ) ;
IXGBE_READ_REG ( hw , IXGBE_MLFC ) ;
IXGBE_READ_REG ( hw , IXGBE_MRFC ) ;
IXGBE_READ_REG ( hw , IXGBE_RLEC ) ;
IXGBE_READ_REG ( hw , IXGBE_LXONTXC ) ;
IXGBE_READ_REG ( hw , IXGBE_LXONRXC ) ;
IXGBE_READ_REG ( hw , IXGBE_LXOFFTXC ) ;
IXGBE_READ_REG ( hw , IXGBE_LXOFFRXC ) ;
for ( i = 0 ; i < 8 ; i + + ) {
IXGBE_READ_REG ( hw , IXGBE_PXONTXC ( i ) ) ;
IXGBE_READ_REG ( hw , IXGBE_PXONRXC ( i ) ) ;
IXGBE_READ_REG ( hw , IXGBE_PXOFFTXC ( i ) ) ;
IXGBE_READ_REG ( hw , IXGBE_PXOFFRXC ( i ) ) ;
}
IXGBE_READ_REG ( hw , IXGBE_PRC64 ) ;
IXGBE_READ_REG ( hw , IXGBE_PRC127 ) ;
IXGBE_READ_REG ( hw , IXGBE_PRC255 ) ;
IXGBE_READ_REG ( hw , IXGBE_PRC511 ) ;
IXGBE_READ_REG ( hw , IXGBE_PRC1023 ) ;
IXGBE_READ_REG ( hw , IXGBE_PRC1522 ) ;
IXGBE_READ_REG ( hw , IXGBE_GPRC ) ;
IXGBE_READ_REG ( hw , IXGBE_BPRC ) ;
IXGBE_READ_REG ( hw , IXGBE_MPRC ) ;
IXGBE_READ_REG ( hw , IXGBE_GPTC ) ;
IXGBE_READ_REG ( hw , IXGBE_GORCL ) ;
IXGBE_READ_REG ( hw , IXGBE_GORCH ) ;
IXGBE_READ_REG ( hw , IXGBE_GOTCL ) ;
IXGBE_READ_REG ( hw , IXGBE_GOTCH ) ;
for ( i = 0 ; i < 8 ; i + + )
IXGBE_READ_REG ( hw , IXGBE_RNBC ( i ) ) ;
IXGBE_READ_REG ( hw , IXGBE_RUC ) ;
IXGBE_READ_REG ( hw , IXGBE_RFC ) ;
IXGBE_READ_REG ( hw , IXGBE_ROC ) ;
IXGBE_READ_REG ( hw , IXGBE_RJC ) ;
IXGBE_READ_REG ( hw , IXGBE_MNGPRC ) ;
IXGBE_READ_REG ( hw , IXGBE_MNGPDC ) ;
IXGBE_READ_REG ( hw , IXGBE_MNGPTC ) ;
IXGBE_READ_REG ( hw , IXGBE_TORL ) ;
IXGBE_READ_REG ( hw , IXGBE_TORH ) ;
IXGBE_READ_REG ( hw , IXGBE_TPR ) ;
IXGBE_READ_REG ( hw , IXGBE_TPT ) ;
IXGBE_READ_REG ( hw , IXGBE_PTC64 ) ;
IXGBE_READ_REG ( hw , IXGBE_PTC127 ) ;
IXGBE_READ_REG ( hw , IXGBE_PTC255 ) ;
IXGBE_READ_REG ( hw , IXGBE_PTC511 ) ;
IXGBE_READ_REG ( hw , IXGBE_PTC1023 ) ;
IXGBE_READ_REG ( hw , IXGBE_PTC1522 ) ;
IXGBE_READ_REG ( hw , IXGBE_MPTC ) ;
IXGBE_READ_REG ( hw , IXGBE_BPTC ) ;
for ( i = 0 ; i < 16 ; i + + ) {
IXGBE_READ_REG ( hw , IXGBE_QPRC ( i ) ) ;
IXGBE_READ_REG ( hw , IXGBE_QBRC ( i ) ) ;
IXGBE_READ_REG ( hw , IXGBE_QPTC ( i ) ) ;
IXGBE_READ_REG ( hw , IXGBE_QBTC ( i ) ) ;
}
return 0 ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_read_pba_num_generic - Reads part number from EEPROM
* @ hw : pointer to hardware structure
* @ pba_num : stores the part number from the EEPROM
*
* Reads the part number from the EEPROM .
* */
s32 ixgbe_read_pba_num_generic ( struct ixgbe_hw * hw , u32 * pba_num )
{
s32 ret_val ;
u16 data ;
ret_val = hw - > eeprom . ops . read ( hw , IXGBE_PBANUM0_PTR , & data ) ;
if ( ret_val ) {
hw_dbg ( hw , " NVM Read Error \n " ) ;
return ret_val ;
}
* pba_num = ( u32 ) ( data < < 16 ) ;
ret_val = hw - > eeprom . ops . read ( hw , IXGBE_PBANUM1_PTR , & data ) ;
if ( ret_val ) {
hw_dbg ( hw , " NVM Read Error \n " ) ;
return ret_val ;
}
* pba_num | = data ;
return 0 ;
}
/**
* ixgbe_get_mac_addr_generic - Generic get MAC address
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
* @ mac_addr : Adapter MAC address
*
* Reads the adapter ' s MAC address from first Receive Address Register ( RAR0 )
* A reset of the adapter must be performed prior to calling this function
* in order for the MAC address to have been loaded from the EEPROM into RAR0
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_get_mac_addr_generic ( struct ixgbe_hw * hw , u8 * mac_addr )
2007-09-16 01:07:45 +04:00
{
u32 rar_high ;
u32 rar_low ;
u16 i ;
rar_high = IXGBE_READ_REG ( hw , IXGBE_RAH ( 0 ) ) ;
rar_low = IXGBE_READ_REG ( hw , IXGBE_RAL ( 0 ) ) ;
for ( i = 0 ; i < 4 ; i + + )
mac_addr [ i ] = ( u8 ) ( rar_low > > ( i * 8 ) ) ;
for ( i = 0 ; i < 2 ; i + + )
mac_addr [ i + 4 ] = ( u8 ) ( rar_high > > ( i * 8 ) ) ;
return 0 ;
}
2009-02-27 18:44:30 +03:00
/**
* ixgbe_get_bus_info_generic - Generic set PCI bus info
* @ hw : pointer to hardware structure
*
* Sets the PCI bus info ( speed , width , type ) within the ixgbe_hw structure
* */
s32 ixgbe_get_bus_info_generic ( struct ixgbe_hw * hw )
{
struct ixgbe_adapter * adapter = hw - > back ;
struct ixgbe_mac_info * mac = & hw - > mac ;
u16 link_status ;
hw - > bus . type = ixgbe_bus_type_pci_express ;
/* Get the negotiated link width and speed from PCI config space */
pci_read_config_word ( adapter - > pdev , IXGBE_PCI_LINK_STATUS ,
& link_status ) ;
switch ( link_status & IXGBE_PCI_LINK_WIDTH ) {
case IXGBE_PCI_LINK_WIDTH_1 :
hw - > bus . width = ixgbe_bus_width_pcie_x1 ;
break ;
case IXGBE_PCI_LINK_WIDTH_2 :
hw - > bus . width = ixgbe_bus_width_pcie_x2 ;
break ;
case IXGBE_PCI_LINK_WIDTH_4 :
hw - > bus . width = ixgbe_bus_width_pcie_x4 ;
break ;
case IXGBE_PCI_LINK_WIDTH_8 :
hw - > bus . width = ixgbe_bus_width_pcie_x8 ;
break ;
default :
hw - > bus . width = ixgbe_bus_width_unknown ;
break ;
}
switch ( link_status & IXGBE_PCI_LINK_SPEED ) {
case IXGBE_PCI_LINK_SPEED_2500 :
hw - > bus . speed = ixgbe_bus_speed_2500 ;
break ;
case IXGBE_PCI_LINK_SPEED_5000 :
hw - > bus . speed = ixgbe_bus_speed_5000 ;
break ;
default :
hw - > bus . speed = ixgbe_bus_speed_unknown ;
break ;
}
mac - > ops . set_lan_id ( hw ) ;
return 0 ;
}
/**
* ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
* @ hw : pointer to the HW structure
*
* Determines the LAN function id by reading memory - mapped registers
* and swaps the port value if requested .
* */
void ixgbe_set_lan_id_multi_port_pcie ( struct ixgbe_hw * hw )
{
struct ixgbe_bus_info * bus = & hw - > bus ;
u32 reg ;
reg = IXGBE_READ_REG ( hw , IXGBE_STATUS ) ;
bus - > func = ( reg & IXGBE_STATUS_LAN_ID ) > > IXGBE_STATUS_LAN_ID_SHIFT ;
bus - > lan_id = bus - > func ;
/* check for a port swap */
reg = IXGBE_READ_REG ( hw , IXGBE_FACTPS ) ;
if ( reg & IXGBE_FACTPS_LFS )
bus - > func ^ = 0x1 ;
}
2007-09-16 01:07:45 +04:00
/**
2008-09-12 06:59:59 +04:00
* ixgbe_stop_adapter_generic - Generic stop Tx / Rx units
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
*
* Sets the adapter_stopped flag within ixgbe_hw struct . Clears interrupts ,
* disables transmit and receive units . The adapter_stopped flag is used by
* the shared code and drivers to determine if the adapter is in a stopped
* state and should not touch the hardware .
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_stop_adapter_generic ( struct ixgbe_hw * hw )
2007-09-16 01:07:45 +04:00
{
u32 number_of_queues ;
u32 reg_val ;
u16 i ;
/*
* Set the adapter_stopped flag so other driver functions stop touching
* the hardware
*/
hw - > adapter_stopped = true ;
/* Disable the receive unit */
reg_val = IXGBE_READ_REG ( hw , IXGBE_RXCTRL ) ;
reg_val & = ~ ( IXGBE_RXCTRL_RXEN ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RXCTRL , reg_val ) ;
2008-09-12 06:59:59 +04:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-16 01:07:45 +04:00
msleep ( 2 ) ;
/* Clear interrupt mask to stop from interrupts being generated */
IXGBE_WRITE_REG ( hw , IXGBE_EIMC , IXGBE_IRQ_CLEAR_MASK ) ;
/* Clear any pending interrupts */
IXGBE_READ_REG ( hw , IXGBE_EICR ) ;
/* Disable the transmit unit. Each queue must be disabled. */
2008-09-12 06:59:59 +04:00
number_of_queues = hw - > mac . max_tx_queues ;
2007-09-16 01:07:45 +04:00
for ( i = 0 ; i < number_of_queues ; i + + ) {
reg_val = IXGBE_READ_REG ( hw , IXGBE_TXDCTL ( i ) ) ;
if ( reg_val & IXGBE_TXDCTL_ENABLE ) {
reg_val & = ~ IXGBE_TXDCTL_ENABLE ;
IXGBE_WRITE_REG ( hw , IXGBE_TXDCTL ( i ) , reg_val ) ;
}
}
2008-09-12 06:59:59 +04:00
/*
* Prevent the PCI - E bus from from hanging by disabling PCI - E master
* access and verify no pending requests
*/
if ( ixgbe_disable_pcie_master ( hw ) ! = 0 )
hw_dbg ( hw , " PCI-E Master disable polling has failed. \n " ) ;
2007-09-16 01:07:45 +04:00
return 0 ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_led_on_generic - Turns on the software controllable LEDs .
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
* @ index : led number to turn on
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_led_on_generic ( struct ixgbe_hw * hw , u32 index )
2007-09-16 01:07:45 +04:00
{
u32 led_reg = IXGBE_READ_REG ( hw , IXGBE_LEDCTL ) ;
/* To turn on the LED, set mode to ON. */
led_reg & = ~ IXGBE_LED_MODE_MASK ( index ) ;
led_reg | = IXGBE_LED_ON < < IXGBE_LED_MODE_SHIFT ( index ) ;
IXGBE_WRITE_REG ( hw , IXGBE_LEDCTL , led_reg ) ;
2007-11-01 01:22:10 +03:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-16 01:07:45 +04:00
return 0 ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_led_off_generic - Turns off the software controllable LEDs .
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
* @ index : led number to turn off
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_led_off_generic ( struct ixgbe_hw * hw , u32 index )
2007-09-16 01:07:45 +04:00
{
u32 led_reg = IXGBE_READ_REG ( hw , IXGBE_LEDCTL ) ;
/* To turn off the LED, set mode to OFF. */
led_reg & = ~ IXGBE_LED_MODE_MASK ( index ) ;
led_reg | = IXGBE_LED_OFF < < IXGBE_LED_MODE_SHIFT ( index ) ;
IXGBE_WRITE_REG ( hw , IXGBE_LEDCTL , led_reg ) ;
2007-11-01 01:22:10 +03:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-16 01:07:45 +04:00
return 0 ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_init_eeprom_params_generic - Initialize EEPROM params
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
*
* Initializes the EEPROM parameters ixgbe_eeprom_info within the
* ixgbe_hw struct in order to set up EEPROM access .
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_init_eeprom_params_generic ( struct ixgbe_hw * hw )
2007-09-16 01:07:45 +04:00
{
struct ixgbe_eeprom_info * eeprom = & hw - > eeprom ;
u32 eec ;
u16 eeprom_size ;
if ( eeprom - > type = = ixgbe_eeprom_uninitialized ) {
eeprom - > type = ixgbe_eeprom_none ;
2008-09-12 06:59:59 +04:00
/* Set default semaphore delay to 10ms which is a well
* tested value */
eeprom - > semaphore_delay = 10 ;
2007-09-16 01:07:45 +04:00
/*
* Check for EEPROM present first .
* If not present leave as none
*/
eec = IXGBE_READ_REG ( hw , IXGBE_EEC ) ;
if ( eec & IXGBE_EEC_PRES ) {
eeprom - > type = ixgbe_eeprom_spi ;
/*
* SPI EEPROM is assumed here . This code would need to
* change if a future EEPROM is not SPI .
*/
eeprom_size = ( u16 ) ( ( eec & IXGBE_EEC_SIZE ) > >
IXGBE_EEC_SIZE_SHIFT ) ;
eeprom - > word_size = 1 < < ( eeprom_size +
IXGBE_EEPROM_WORD_SIZE_SHIFT ) ;
}
if ( eec & IXGBE_EEC_ADDR_SIZE )
eeprom - > address_bits = 16 ;
else
eeprom - > address_bits = 8 ;
hw_dbg ( hw , " Eeprom params: type = %d, size = %d, address bits: "
" %d \n " , eeprom - > type , eeprom - > word_size ,
eeprom - > address_bits ) ;
}
return 0 ;
}
2009-02-27 18:44:30 +03:00
/**
* ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
* @ hw : pointer to hardware structure
* @ offset : offset within the EEPROM to be written to
* @ data : 16 bit word to be written to the EEPROM
*
* If ixgbe_eeprom_update_checksum is not called after this function , the
* EEPROM will most likely contain an invalid checksum .
* */
s32 ixgbe_write_eeprom_generic ( struct ixgbe_hw * hw , u16 offset , u16 data )
{
s32 status ;
u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI ;
hw - > eeprom . ops . init_params ( hw ) ;
if ( offset > = hw - > eeprom . word_size ) {
status = IXGBE_ERR_EEPROM ;
goto out ;
}
/* Prepare the EEPROM for writing */
status = ixgbe_acquire_eeprom ( hw ) ;
if ( status = = 0 ) {
if ( ixgbe_ready_eeprom ( hw ) ! = 0 ) {
ixgbe_release_eeprom ( hw ) ;
status = IXGBE_ERR_EEPROM ;
}
}
if ( status = = 0 ) {
ixgbe_standby_eeprom ( hw ) ;
/* Send the WRITE ENABLE command (8 bit opcode ) */
ixgbe_shift_out_eeprom_bits ( hw , IXGBE_EEPROM_WREN_OPCODE_SPI ,
IXGBE_EEPROM_OPCODE_BITS ) ;
ixgbe_standby_eeprom ( hw ) ;
/*
* Some SPI eeproms use the 8 th address bit embedded in the
* opcode
*/
if ( ( hw - > eeprom . address_bits = = 8 ) & & ( offset > = 128 ) )
write_opcode | = IXGBE_EEPROM_A8_OPCODE_SPI ;
/* Send the Write command (8-bit opcode + addr) */
ixgbe_shift_out_eeprom_bits ( hw , write_opcode ,
IXGBE_EEPROM_OPCODE_BITS ) ;
ixgbe_shift_out_eeprom_bits ( hw , ( u16 ) ( offset * 2 ) ,
hw - > eeprom . address_bits ) ;
/* Send the data */
data = ( data > > 8 ) | ( data < < 8 ) ;
ixgbe_shift_out_eeprom_bits ( hw , data , 16 ) ;
ixgbe_standby_eeprom ( hw ) ;
msleep ( hw - > eeprom . semaphore_delay ) ;
/* Done with writing - release the EEPROM */
ixgbe_release_eeprom ( hw ) ;
}
out :
return status ;
}
2007-09-16 01:07:45 +04:00
/**
2008-09-12 06:59:59 +04:00
* ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit - bang
* @ hw : pointer to hardware structure
* @ offset : offset within the EEPROM to be read
* @ data : read 16 bit value from EEPROM
*
* Reads 16 bit value from EEPROM through bit - bang method
* */
s32 ixgbe_read_eeprom_bit_bang_generic ( struct ixgbe_hw * hw , u16 offset ,
u16 * data )
{
s32 status ;
u16 word_in ;
u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI ;
hw - > eeprom . ops . init_params ( hw ) ;
if ( offset > = hw - > eeprom . word_size ) {
status = IXGBE_ERR_EEPROM ;
goto out ;
}
/* Prepare the EEPROM for reading */
status = ixgbe_acquire_eeprom ( hw ) ;
if ( status = = 0 ) {
if ( ixgbe_ready_eeprom ( hw ) ! = 0 ) {
ixgbe_release_eeprom ( hw ) ;
status = IXGBE_ERR_EEPROM ;
}
}
if ( status = = 0 ) {
ixgbe_standby_eeprom ( hw ) ;
/*
* Some SPI eeproms use the 8 th address bit embedded in the
* opcode
*/
if ( ( hw - > eeprom . address_bits = = 8 ) & & ( offset > = 128 ) )
read_opcode | = IXGBE_EEPROM_A8_OPCODE_SPI ;
/* Send the READ command (opcode + addr) */
ixgbe_shift_out_eeprom_bits ( hw , read_opcode ,
IXGBE_EEPROM_OPCODE_BITS ) ;
ixgbe_shift_out_eeprom_bits ( hw , ( u16 ) ( offset * 2 ) ,
hw - > eeprom . address_bits ) ;
/* Read the data. */
word_in = ixgbe_shift_in_eeprom_bits ( hw , 16 ) ;
* data = ( word_in > > 8 ) | ( word_in < < 8 ) ;
/* End this read operation */
ixgbe_release_eeprom ( hw ) ;
}
out :
return status ;
}
/**
2010-05-13 21:33:41 +04:00
* ixgbe_read_eerd_generic - Read EEPROM word using EERD
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
* @ offset : offset of word in the EEPROM to read
* @ data : word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM using the EERD register .
* */
2010-05-13 21:33:41 +04:00
s32 ixgbe_read_eerd_generic ( struct ixgbe_hw * hw , u16 offset , u16 * data )
2007-09-16 01:07:45 +04:00
{
u32 eerd ;
s32 status ;
2008-09-12 06:59:59 +04:00
hw - > eeprom . ops . init_params ( hw ) ;
if ( offset > = hw - > eeprom . word_size ) {
status = IXGBE_ERR_EEPROM ;
goto out ;
}
2010-05-13 21:33:41 +04:00
eerd = ( offset < < IXGBE_EEPROM_RW_ADDR_SHIFT ) +
IXGBE_EEPROM_RW_REG_START ;
2007-09-16 01:07:45 +04:00
IXGBE_WRITE_REG ( hw , IXGBE_EERD , eerd ) ;
2010-05-13 21:33:41 +04:00
status = ixgbe_poll_eerd_eewr_done ( hw , IXGBE_NVM_POLL_READ ) ;
2007-09-16 01:07:45 +04:00
if ( status = = 0 )
* data = ( IXGBE_READ_REG ( hw , IXGBE_EERD ) > >
2010-05-13 21:33:41 +04:00
IXGBE_EEPROM_RW_REG_DATA ) ;
2007-09-16 01:07:45 +04:00
else
hw_dbg ( hw , " Eeprom read timed out \n " ) ;
2008-09-12 06:59:59 +04:00
out :
2007-09-16 01:07:45 +04:00
return status ;
}
/**
2010-05-13 21:33:41 +04:00
* ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
2010-05-13 21:33:41 +04:00
* @ ee_reg : EEPROM flag for polling
2007-09-16 01:07:45 +04:00
*
2010-05-13 21:33:41 +04:00
* Polls the status bit ( bit 1 ) of the EERD or EEWR to determine when the
* read or write is done respectively .
2007-09-16 01:07:45 +04:00
* */
2010-05-13 21:33:41 +04:00
s32 ixgbe_poll_eerd_eewr_done ( struct ixgbe_hw * hw , u32 ee_reg )
2007-09-16 01:07:45 +04:00
{
u32 i ;
u32 reg ;
s32 status = IXGBE_ERR_EEPROM ;
2010-05-13 21:33:41 +04:00
for ( i = 0 ; i < IXGBE_EERD_EEWR_ATTEMPTS ; i + + ) {
if ( ee_reg = = IXGBE_NVM_POLL_READ )
reg = IXGBE_READ_REG ( hw , IXGBE_EERD ) ;
else
reg = IXGBE_READ_REG ( hw , IXGBE_EEWR ) ;
if ( reg & IXGBE_EEPROM_RW_REG_DONE ) {
2007-09-16 01:07:45 +04:00
status = 0 ;
break ;
}
udelay ( 5 ) ;
}
return status ;
}
2008-09-12 06:59:59 +04:00
/**
* ixgbe_acquire_eeprom - Acquire EEPROM using bit - bang
* @ hw : pointer to hardware structure
*
* Prepares EEPROM for access using bit - bang method . This function should
* be called before issuing a command to the EEPROM .
* */
static s32 ixgbe_acquire_eeprom ( struct ixgbe_hw * hw )
{
s32 status = 0 ;
2009-03-02 07:32:39 +03:00
u32 eec = 0 ;
2008-09-12 06:59:59 +04:00
u32 i ;
if ( ixgbe_acquire_swfw_sync ( hw , IXGBE_GSSR_EEP_SM ) ! = 0 )
status = IXGBE_ERR_SWFW_SYNC ;
if ( status = = 0 ) {
eec = IXGBE_READ_REG ( hw , IXGBE_EEC ) ;
/* Request EEPROM Access */
eec | = IXGBE_EEC_REQ ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
for ( i = 0 ; i < IXGBE_EEPROM_GRANT_ATTEMPTS ; i + + ) {
eec = IXGBE_READ_REG ( hw , IXGBE_EEC ) ;
if ( eec & IXGBE_EEC_GNT )
break ;
udelay ( 5 ) ;
}
/* Release if grant not acquired */
if ( ! ( eec & IXGBE_EEC_GNT ) ) {
eec & = ~ IXGBE_EEC_REQ ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
hw_dbg ( hw , " Could not acquire EEPROM grant \n " ) ;
ixgbe_release_swfw_sync ( hw , IXGBE_GSSR_EEP_SM ) ;
status = IXGBE_ERR_EEPROM ;
}
}
/* Setup EEPROM for Read/Write */
if ( status = = 0 ) {
/* Clear CS and SK */
eec & = ~ ( IXGBE_EEC_CS | IXGBE_EEC_SK ) ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 1 ) ;
}
return status ;
}
2007-09-16 01:07:45 +04:00
/**
* ixgbe_get_eeprom_semaphore - Get hardware semaphore
* @ hw : pointer to hardware structure
*
* Sets the hardware semaphores so EEPROM access can occur for bit - bang method
* */
static s32 ixgbe_get_eeprom_semaphore ( struct ixgbe_hw * hw )
{
s32 status = IXGBE_ERR_EEPROM ;
u32 timeout ;
u32 i ;
u32 swsm ;
/* Set timeout value based on size of EEPROM */
timeout = hw - > eeprom . word_size + 1 ;
/* Get SMBI software semaphore between device drivers first */
for ( i = 0 ; i < timeout ; i + + ) {
/*
* If the SMBI bit is 0 when we read it , then the bit will be
* set and we have the semaphore
*/
swsm = IXGBE_READ_REG ( hw , IXGBE_SWSM ) ;
if ( ! ( swsm & IXGBE_SWSM_SMBI ) ) {
status = 0 ;
break ;
}
msleep ( 1 ) ;
}
/* Now get the semaphore between SW/FW through the SWESMBI bit */
if ( status = = 0 ) {
for ( i = 0 ; i < timeout ; i + + ) {
swsm = IXGBE_READ_REG ( hw , IXGBE_SWSM ) ;
/* Set the SW EEPROM semaphore bit to request access */
swsm | = IXGBE_SWSM_SWESMBI ;
IXGBE_WRITE_REG ( hw , IXGBE_SWSM , swsm ) ;
/*
* If we set the bit successfully then we got the
* semaphore .
*/
swsm = IXGBE_READ_REG ( hw , IXGBE_SWSM ) ;
if ( swsm & IXGBE_SWSM_SWESMBI )
break ;
udelay ( 50 ) ;
}
/*
* Release semaphores and return error if SW EEPROM semaphore
* was not granted because we don ' t have access to the EEPROM
*/
if ( i > = timeout ) {
hw_dbg ( hw , " Driver can't access the Eeprom - Semaphore "
2008-09-12 07:04:46 +04:00
" not granted. \n " ) ;
2007-09-16 01:07:45 +04:00
ixgbe_release_eeprom_semaphore ( hw ) ;
status = IXGBE_ERR_EEPROM ;
}
}
return status ;
}
/**
* ixgbe_release_eeprom_semaphore - Release hardware semaphore
* @ hw : pointer to hardware structure
*
* This function clears hardware semaphore bits .
* */
static void ixgbe_release_eeprom_semaphore ( struct ixgbe_hw * hw )
{
u32 swsm ;
swsm = IXGBE_READ_REG ( hw , IXGBE_SWSM ) ;
/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
swsm & = ~ ( IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI ) ;
IXGBE_WRITE_REG ( hw , IXGBE_SWSM , swsm ) ;
2007-11-01 01:22:10 +03:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-16 01:07:45 +04:00
}
2008-09-12 06:59:59 +04:00
/**
* ixgbe_ready_eeprom - Polls for EEPROM ready
* @ hw : pointer to hardware structure
* */
static s32 ixgbe_ready_eeprom ( struct ixgbe_hw * hw )
{
s32 status = 0 ;
u16 i ;
u8 spi_stat_reg ;
/*
* Read " Status Register " repeatedly until the LSB is cleared . The
* EEPROM will signal that the command has been completed by clearing
* bit 0 of the internal status register . If it ' s not cleared within
* 5 milliseconds , then error out .
*/
for ( i = 0 ; i < IXGBE_EEPROM_MAX_RETRY_SPI ; i + = 5 ) {
ixgbe_shift_out_eeprom_bits ( hw , IXGBE_EEPROM_RDSR_OPCODE_SPI ,
IXGBE_EEPROM_OPCODE_BITS ) ;
spi_stat_reg = ( u8 ) ixgbe_shift_in_eeprom_bits ( hw , 8 ) ;
if ( ! ( spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI ) )
break ;
udelay ( 5 ) ;
ixgbe_standby_eeprom ( hw ) ;
} ;
/*
* On some parts , SPI write time could vary from 0 - 20 mSec on 3.3 V
* devices ( and only 0 - 5 mSec on 5 V devices )
*/
if ( i > = IXGBE_EEPROM_MAX_RETRY_SPI ) {
hw_dbg ( hw , " SPI EEPROM Status error \n " ) ;
status = IXGBE_ERR_EEPROM ;
}
return status ;
}
/**
* ixgbe_standby_eeprom - Returns EEPROM to a " standby " state
* @ hw : pointer to hardware structure
* */
static void ixgbe_standby_eeprom ( struct ixgbe_hw * hw )
{
u32 eec ;
eec = IXGBE_READ_REG ( hw , IXGBE_EEC ) ;
/* Toggle CS to flush commands */
eec | = IXGBE_EEC_CS ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 1 ) ;
eec & = ~ IXGBE_EEC_CS ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 1 ) ;
}
/**
* ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM .
* @ hw : pointer to hardware structure
* @ data : data to send to the EEPROM
* @ count : number of bits to shift out
* */
static void ixgbe_shift_out_eeprom_bits ( struct ixgbe_hw * hw , u16 data ,
u16 count )
{
u32 eec ;
u32 mask ;
u32 i ;
eec = IXGBE_READ_REG ( hw , IXGBE_EEC ) ;
/*
* Mask is used to shift " count " bits of " data " out to the EEPROM
* one bit at a time . Determine the starting bit based on count
*/
mask = 0x01 < < ( count - 1 ) ;
for ( i = 0 ; i < count ; i + + ) {
/*
* A " 1 " is shifted out to the EEPROM by setting bit " DI " to a
* " 1 " , and then raising and then lowering the clock ( the SK
* bit controls the clock input to the EEPROM ) . A " 0 " is
* shifted out to the EEPROM by setting " DI " to " 0 " and then
* raising and then lowering the clock .
*/
if ( data & mask )
eec | = IXGBE_EEC_DI ;
else
eec & = ~ IXGBE_EEC_DI ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 1 ) ;
ixgbe_raise_eeprom_clk ( hw , & eec ) ;
ixgbe_lower_eeprom_clk ( hw , & eec ) ;
/*
* Shift mask to signify next bit of data to shift in to the
* EEPROM
*/
mask = mask > > 1 ;
} ;
/* We leave the "DI" bit set to "0" when we leave this routine. */
eec & = ~ IXGBE_EEC_DI ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
}
/**
* ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
* @ hw : pointer to hardware structure
* */
static u16 ixgbe_shift_in_eeprom_bits ( struct ixgbe_hw * hw , u16 count )
{
u32 eec ;
u32 i ;
u16 data = 0 ;
/*
* In order to read a register from the EEPROM , we need to shift
* ' count ' bits in from the EEPROM . Bits are " shifted in " by raising
* the clock input to the EEPROM ( setting the SK bit ) , and then reading
* the value of the " DO " bit . During this " shifting in " process the
* " DI " bit should always be clear .
*/
eec = IXGBE_READ_REG ( hw , IXGBE_EEC ) ;
eec & = ~ ( IXGBE_EEC_DO | IXGBE_EEC_DI ) ;
for ( i = 0 ; i < count ; i + + ) {
data = data < < 1 ;
ixgbe_raise_eeprom_clk ( hw , & eec ) ;
eec = IXGBE_READ_REG ( hw , IXGBE_EEC ) ;
eec & = ~ ( IXGBE_EEC_DI ) ;
if ( eec & IXGBE_EEC_DO )
data | = 1 ;
ixgbe_lower_eeprom_clk ( hw , & eec ) ;
}
return data ;
}
/**
* ixgbe_raise_eeprom_clk - Raises the EEPROM ' s clock input .
* @ hw : pointer to hardware structure
* @ eec : EEC register ' s current value
* */
static void ixgbe_raise_eeprom_clk ( struct ixgbe_hw * hw , u32 * eec )
{
/*
* Raise the clock input to the EEPROM
* ( setting the SK bit ) , then delay
*/
* eec = * eec | IXGBE_EEC_SK ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , * eec ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 1 ) ;
}
/**
* ixgbe_lower_eeprom_clk - Lowers the EEPROM ' s clock input .
* @ hw : pointer to hardware structure
* @ eecd : EECD ' s current value
* */
static void ixgbe_lower_eeprom_clk ( struct ixgbe_hw * hw , u32 * eec )
{
/*
* Lower the clock input to the EEPROM ( clearing the SK bit ) , then
* delay
*/
* eec = * eec & ~ IXGBE_EEC_SK ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , * eec ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 1 ) ;
}
/**
* ixgbe_release_eeprom - Release EEPROM , release semaphores
* @ hw : pointer to hardware structure
* */
static void ixgbe_release_eeprom ( struct ixgbe_hw * hw )
{
u32 eec ;
eec = IXGBE_READ_REG ( hw , IXGBE_EEC ) ;
eec | = IXGBE_EEC_CS ; /* Pull CS high */
eec & = ~ IXGBE_EEC_SK ; /* Lower SCK */
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 1 ) ;
/* Stop requesting EEPROM access */
eec & = ~ IXGBE_EEC_REQ ;
IXGBE_WRITE_REG ( hw , IXGBE_EEC , eec ) ;
ixgbe_release_swfw_sync ( hw , IXGBE_GSSR_EEP_SM ) ;
}
2007-09-16 01:07:45 +04:00
/**
* ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
* @ hw : pointer to hardware structure
* */
static u16 ixgbe_calc_eeprom_checksum ( struct ixgbe_hw * hw )
{
u16 i ;
u16 j ;
u16 checksum = 0 ;
u16 length = 0 ;
u16 pointer = 0 ;
u16 word = 0 ;
/* Include 0x0-0x3F in the checksum */
for ( i = 0 ; i < IXGBE_EEPROM_CHECKSUM ; i + + ) {
2008-09-12 06:59:59 +04:00
if ( hw - > eeprom . ops . read ( hw , i , & word ) ! = 0 ) {
2007-09-16 01:07:45 +04:00
hw_dbg ( hw , " EEPROM read failed \n " ) ;
break ;
}
checksum + = word ;
}
/* Include all data from pointers except for the fw pointer */
for ( i = IXGBE_PCIE_ANALOG_PTR ; i < IXGBE_FW_PTR ; i + + ) {
2008-09-12 06:59:59 +04:00
hw - > eeprom . ops . read ( hw , i , & pointer ) ;
2007-09-16 01:07:45 +04:00
/* Make sure the pointer seems valid */
if ( pointer ! = 0xFFFF & & pointer ! = 0 ) {
2008-09-12 06:59:59 +04:00
hw - > eeprom . ops . read ( hw , pointer , & length ) ;
2007-09-16 01:07:45 +04:00
if ( length ! = 0xFFFF & & length ! = 0 ) {
for ( j = pointer + 1 ; j < = pointer + length ; j + + ) {
2008-09-12 06:59:59 +04:00
hw - > eeprom . ops . read ( hw , j , & word ) ;
2007-09-16 01:07:45 +04:00
checksum + = word ;
}
}
}
}
checksum = ( u16 ) IXGBE_EEPROM_SUM - checksum ;
return checksum ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
* @ checksum_val : calculated checksum
*
* Performs checksum calculation and validates the EEPROM checksum . If the
* caller does not need checksum_val , the value can be NULL .
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_validate_eeprom_checksum_generic ( struct ixgbe_hw * hw ,
u16 * checksum_val )
2007-09-16 01:07:45 +04:00
{
s32 status ;
u16 checksum ;
u16 read_checksum = 0 ;
/*
* Read the first word from the EEPROM . If this times out or fails , do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
2008-09-12 06:59:59 +04:00
status = hw - > eeprom . ops . read ( hw , 0 , & checksum ) ;
2007-09-16 01:07:45 +04:00
if ( status = = 0 ) {
checksum = ixgbe_calc_eeprom_checksum ( hw ) ;
2008-09-12 06:59:59 +04:00
hw - > eeprom . ops . read ( hw , IXGBE_EEPROM_CHECKSUM , & read_checksum ) ;
2007-09-16 01:07:45 +04:00
/*
* Verify read checksum from EEPROM is the same as
* calculated checksum
*/
if ( read_checksum ! = checksum )
status = IXGBE_ERR_EEPROM_CHECKSUM ;
/* If the user cares, return the calculated checksum */
if ( checksum_val )
* checksum_val = checksum ;
} else {
hw_dbg ( hw , " EEPROM read failed \n " ) ;
}
return status ;
}
2008-09-12 06:59:59 +04:00
/**
* ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum
* @ hw : pointer to hardware structure
* */
s32 ixgbe_update_eeprom_checksum_generic ( struct ixgbe_hw * hw )
{
s32 status ;
u16 checksum ;
/*
* Read the first word from the EEPROM . If this times out or fails , do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
status = hw - > eeprom . ops . read ( hw , 0 , & checksum ) ;
if ( status = = 0 ) {
checksum = ixgbe_calc_eeprom_checksum ( hw ) ;
status = hw - > eeprom . ops . write ( hw , IXGBE_EEPROM_CHECKSUM ,
checksum ) ;
} else {
hw_dbg ( hw , " EEPROM read failed \n " ) ;
}
return status ;
}
2007-09-16 01:07:45 +04:00
/**
* ixgbe_validate_mac_addr - Validate MAC address
* @ mac_addr : pointer to MAC address .
*
* Tests a MAC address to ensure it is a valid Individual Address
* */
s32 ixgbe_validate_mac_addr ( u8 * mac_addr )
{
s32 status = 0 ;
/* Make sure it is not a multicast address */
if ( IXGBE_IS_MULTICAST ( mac_addr ) )
status = IXGBE_ERR_INVALID_MAC_ADDR ;
/* Not a broadcast address */
else if ( IXGBE_IS_BROADCAST ( mac_addr ) )
status = IXGBE_ERR_INVALID_MAC_ADDR ;
/* Reject the zero address */
else if ( mac_addr [ 0 ] = = 0 & & mac_addr [ 1 ] = = 0 & & mac_addr [ 2 ] = = 0 & &
2008-09-12 06:59:59 +04:00
mac_addr [ 3 ] = = 0 & & mac_addr [ 4 ] = = 0 & & mac_addr [ 5 ] = = 0 )
2007-09-16 01:07:45 +04:00
status = IXGBE_ERR_INVALID_MAC_ADDR ;
return status ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_set_rar_generic - Set Rx address register
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
* @ index : Receive address register to write
2008-09-12 06:59:59 +04:00
* @ addr : Address to put into receive address register
* @ vmdq : VMDq " set " or " pool " index
2007-09-16 01:07:45 +04:00
* @ enable_addr : set flag that address is active
*
* Puts an ethernet address into a receive address register .
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_set_rar_generic ( struct ixgbe_hw * hw , u32 index , u8 * addr , u32 vmdq ,
u32 enable_addr )
2007-09-16 01:07:45 +04:00
{
u32 rar_low , rar_high ;
2008-09-12 06:59:59 +04:00
u32 rar_entries = hw - > mac . num_rar_entries ;
/* setup VMDq pool selection before this RAR gets enabled */
hw - > mac . ops . set_vmdq ( hw , index , vmdq ) ;
2007-09-16 01:07:45 +04:00
2008-09-12 06:59:59 +04:00
/* Make sure we are using a valid rar index range */
if ( index < rar_entries ) {
2008-09-12 07:04:46 +04:00
/*
2008-09-12 06:59:59 +04:00
* HW expects these in little endian so we reverse the byte
* order from network order ( big endian ) to little endian
2008-09-12 07:04:46 +04:00
*/
rar_low = ( ( u32 ) addr [ 0 ] |
( ( u32 ) addr [ 1 ] < < 8 ) |
( ( u32 ) addr [ 2 ] < < 16 ) |
( ( u32 ) addr [ 3 ] < < 24 ) ) ;
2008-09-12 06:59:59 +04:00
/*
* Some parts put the VMDq setting in the extra RAH bits ,
* so save everything except the lower 16 bits that hold part
* of the address and the address valid bit .
*/
rar_high = IXGBE_READ_REG ( hw , IXGBE_RAH ( index ) ) ;
rar_high & = ~ ( 0x0000FFFF | IXGBE_RAH_AV ) ;
rar_high | = ( ( u32 ) addr [ 4 ] | ( ( u32 ) addr [ 5 ] < < 8 ) ) ;
2007-09-16 01:07:45 +04:00
2008-09-12 07:04:46 +04:00
if ( enable_addr ! = 0 )
rar_high | = IXGBE_RAH_AV ;
2007-09-16 01:07:45 +04:00
2008-09-12 07:04:46 +04:00
IXGBE_WRITE_REG ( hw , IXGBE_RAL ( index ) , rar_low ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RAH ( index ) , rar_high ) ;
2008-09-12 06:59:59 +04:00
} else {
hw_dbg ( hw , " RAR index %d is out of range. \n " , index ) ;
2010-06-02 16:44:05 +04:00
return IXGBE_ERR_RAR_INDEX ;
2008-09-12 06:59:59 +04:00
}
return 0 ;
}
/**
* ixgbe_clear_rar_generic - Remove Rx address register
* @ hw : pointer to hardware structure
* @ index : Receive address register to write
*
* Clears an ethernet address from a receive address register .
* */
s32 ixgbe_clear_rar_generic ( struct ixgbe_hw * hw , u32 index )
{
u32 rar_high ;
u32 rar_entries = hw - > mac . num_rar_entries ;
/* Make sure we are using a valid rar index range */
if ( index < rar_entries ) {
/*
* Some parts put the VMDq setting in the extra RAH bits ,
* so save everything except the lower 16 bits that hold part
* of the address and the address valid bit .
*/
rar_high = IXGBE_READ_REG ( hw , IXGBE_RAH ( index ) ) ;
rar_high & = ~ ( 0x0000FFFF | IXGBE_RAH_AV ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RAL ( index ) , 0 ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RAH ( index ) , rar_high ) ;
} else {
hw_dbg ( hw , " RAR index %d is out of range. \n " , index ) ;
2010-06-02 16:44:05 +04:00
return IXGBE_ERR_RAR_INDEX ;
2008-09-12 06:59:59 +04:00
}
/* clear VMDq pool/queue selection for this RAR */
hw - > mac . ops . clear_vmdq ( hw , index , IXGBE_CLEAR_VMDQ_ALL ) ;
2007-09-16 01:07:45 +04:00
return 0 ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_enable_rar - Enable Rx address register
* @ hw : pointer to hardware structure
* @ index : index into the RAR table
*
* Enables the select receive address register .
* */
static void ixgbe_enable_rar ( struct ixgbe_hw * hw , u32 index )
{
u32 rar_high ;
rar_high = IXGBE_READ_REG ( hw , IXGBE_RAH ( index ) ) ;
rar_high | = IXGBE_RAH_AV ;
IXGBE_WRITE_REG ( hw , IXGBE_RAH ( index ) , rar_high ) ;
}
/**
* ixgbe_disable_rar - Disable Rx address register
* @ hw : pointer to hardware structure
* @ index : index into the RAR table
*
* Disables the select receive address register .
* */
static void ixgbe_disable_rar ( struct ixgbe_hw * hw , u32 index )
{
u32 rar_high ;
rar_high = IXGBE_READ_REG ( hw , IXGBE_RAH ( index ) ) ;
rar_high & = ( ~ IXGBE_RAH_AV ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RAH ( index ) , rar_high ) ;
}
/**
* ixgbe_init_rx_addrs_generic - Initializes receive address filters .
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
*
* Places the MAC address in receive address register 0 and clears the rest
2008-09-12 06:59:59 +04:00
* of the receive address registers . Clears the multicast table . Assumes
2007-09-16 01:07:45 +04:00
* the receiver is in reset when the routine is called .
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_init_rx_addrs_generic ( struct ixgbe_hw * hw )
2007-09-16 01:07:45 +04:00
{
u32 i ;
2008-08-26 15:27:02 +04:00
u32 rar_entries = hw - > mac . num_rar_entries ;
2007-09-16 01:07:45 +04:00
/*
* If the current mac address is valid , assume it is a software override
* to the permanent address .
* Otherwise , use the permanent address from the eeprom .
*/
if ( ixgbe_validate_mac_addr ( hw - > mac . addr ) = =
IXGBE_ERR_INVALID_MAC_ADDR ) {
/* Get the MAC address from the RAR0 for later reference */
2008-09-12 06:59:59 +04:00
hw - > mac . ops . get_mac_addr ( hw , hw - > mac . addr ) ;
2007-09-16 01:07:45 +04:00
2010-01-05 09:56:52 +03:00
hw_dbg ( hw , " Keeping Current RAR0 Addr =%pM \n " , hw - > mac . addr ) ;
2007-09-16 01:07:45 +04:00
} else {
/* Setup the receive address. */
hw_dbg ( hw , " Overriding MAC Address in RAR[0] \n " ) ;
2010-01-05 09:56:52 +03:00
hw_dbg ( hw , " New MAC Addr =%pM \n " , hw - > mac . addr ) ;
2007-09-16 01:07:45 +04:00
2008-09-12 06:59:59 +04:00
hw - > mac . ops . set_rar ( hw , 0 , hw - > mac . addr , 0 , IXGBE_RAH_AV ) ;
2007-09-16 01:07:45 +04:00
}
2008-09-12 06:59:59 +04:00
hw - > addr_ctrl . overflow_promisc = 0 ;
2007-09-16 01:07:45 +04:00
hw - > addr_ctrl . rar_used_count = 1 ;
/* Zero out the other receive addresses. */
2008-09-12 06:59:59 +04:00
hw_dbg ( hw , " Clearing RAR[1-%d] \n " , rar_entries - 1 ) ;
2007-09-16 01:07:45 +04:00
for ( i = 1 ; i < rar_entries ; i + + ) {
IXGBE_WRITE_REG ( hw , IXGBE_RAL ( i ) , 0 ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RAH ( i ) , 0 ) ;
}
/* Clear the MTA */
hw - > addr_ctrl . mc_addr_in_rar_count = 0 ;
hw - > addr_ctrl . mta_in_use = 0 ;
IXGBE_WRITE_REG ( hw , IXGBE_MCSTCTRL , hw - > mac . mc_filter_type ) ;
hw_dbg ( hw , " Clearing MTA \n " ) ;
2008-08-26 15:27:02 +04:00
for ( i = 0 ; i < hw - > mac . mcft_size ; i + + )
2007-09-16 01:07:45 +04:00
IXGBE_WRITE_REG ( hw , IXGBE_MTA ( i ) , 0 ) ;
2008-09-12 06:59:59 +04:00
if ( hw - > mac . ops . init_uta_tables )
hw - > mac . ops . init_uta_tables ( hw ) ;
2007-09-16 01:07:45 +04:00
return 0 ;
}
2008-08-26 15:27:02 +04:00
/**
* ixgbe_add_uc_addr - Adds a secondary unicast address .
* @ hw : pointer to hardware structure
* @ addr : new address
*
* Adds it to unused receive address register or goes into promiscuous mode .
* */
2008-09-12 06:59:59 +04:00
static void ixgbe_add_uc_addr ( struct ixgbe_hw * hw , u8 * addr , u32 vmdq )
2008-08-26 15:27:02 +04:00
{
u32 rar_entries = hw - > mac . num_rar_entries ;
u32 rar ;
hw_dbg ( hw , " UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X \n " ,
addr [ 0 ] , addr [ 1 ] , addr [ 2 ] , addr [ 3 ] , addr [ 4 ] , addr [ 5 ] ) ;
/*
* Place this address in the RAR if there is room ,
* else put the controller into promiscuous mode
*/
if ( hw - > addr_ctrl . rar_used_count < rar_entries ) {
rar = hw - > addr_ctrl . rar_used_count -
hw - > addr_ctrl . mc_addr_in_rar_count ;
2008-09-12 06:59:59 +04:00
hw - > mac . ops . set_rar ( hw , rar , addr , vmdq , IXGBE_RAH_AV ) ;
2008-08-26 15:27:02 +04:00
hw_dbg ( hw , " Added a secondary address to RAR[%d] \n " , rar ) ;
hw - > addr_ctrl . rar_used_count + + ;
} else {
hw - > addr_ctrl . overflow_promisc + + ;
}
hw_dbg ( hw , " ixgbe_add_uc_addr Complete \n " ) ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
2008-08-26 15:27:02 +04:00
* @ hw : pointer to hardware structure
2010-01-26 00:36:10 +03:00
* @ netdev : pointer to net device structure
2008-08-26 15:27:02 +04:00
*
* The given list replaces any existing list . Clears the secondary addrs from
* receive address registers . Uses unused receive address registers for the
* first secondary addresses , and falls back to promiscuous mode as needed .
*
* Drivers using secondary unicast addresses must set user_set_promisc when
* manually putting the device into promiscuous mode .
* */
2009-05-23 03:22:17 +04:00
s32 ixgbe_update_uc_addr_list_generic ( struct ixgbe_hw * hw ,
2010-01-26 00:36:10 +03:00
struct net_device * netdev )
2008-08-26 15:27:02 +04:00
{
u32 i ;
u32 old_promisc_setting = hw - > addr_ctrl . overflow_promisc ;
u32 uc_addr_in_use ;
u32 fctrl ;
2009-05-23 03:22:17 +04:00
struct netdev_hw_addr * ha ;
2008-08-26 15:27:02 +04:00
/*
* Clear accounting of old secondary address list ,
* don ' t count RAR [ 0 ]
*/
2009-04-23 15:15:18 +04:00
uc_addr_in_use = hw - > addr_ctrl . rar_used_count - 1 ;
2008-08-26 15:27:02 +04:00
hw - > addr_ctrl . rar_used_count - = uc_addr_in_use ;
hw - > addr_ctrl . overflow_promisc = 0 ;
/* Zero out the other receive addresses */
2009-11-24 21:52:10 +03:00
hw_dbg ( hw , " Clearing RAR[1-%d] \n " , uc_addr_in_use + 1 ) ;
for ( i = 0 ; i < uc_addr_in_use ; i + + ) {
IXGBE_WRITE_REG ( hw , IXGBE_RAL ( 1 + i ) , 0 ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RAH ( 1 + i ) , 0 ) ;
2008-08-26 15:27:02 +04:00
}
/* Add the new addresses */
2010-01-26 00:36:10 +03:00
netdev_for_each_uc_addr ( ha , netdev ) {
2008-08-26 15:27:02 +04:00
hw_dbg ( hw , " Adding the secondary addresses: \n " ) ;
2009-05-23 03:22:17 +04:00
ixgbe_add_uc_addr ( hw , ha - > addr , 0 ) ;
2008-08-26 15:27:02 +04:00
}
if ( hw - > addr_ctrl . overflow_promisc ) {
/* enable promisc if not already in overflow or set by user */
if ( ! old_promisc_setting & & ! hw - > addr_ctrl . user_set_promisc ) {
hw_dbg ( hw , " Entering address overflow promisc mode \n " ) ;
fctrl = IXGBE_READ_REG ( hw , IXGBE_FCTRL ) ;
fctrl | = IXGBE_FCTRL_UPE ;
IXGBE_WRITE_REG ( hw , IXGBE_FCTRL , fctrl ) ;
2010-05-13 21:33:00 +04:00
hw - > addr_ctrl . uc_set_promisc = true ;
2008-08-26 15:27:02 +04:00
}
} else {
/* only disable if set by overflow, not by user */
2010-05-13 21:33:00 +04:00
if ( ( old_promisc_setting & & hw - > addr_ctrl . uc_set_promisc ) & &
! ( hw - > addr_ctrl . user_set_promisc ) ) {
2008-08-26 15:27:02 +04:00
hw_dbg ( hw , " Leaving address overflow promisc mode \n " ) ;
fctrl = IXGBE_READ_REG ( hw , IXGBE_FCTRL ) ;
fctrl & = ~ IXGBE_FCTRL_UPE ;
IXGBE_WRITE_REG ( hw , IXGBE_FCTRL , fctrl ) ;
2010-05-13 21:33:00 +04:00
hw - > addr_ctrl . uc_set_promisc = false ;
2008-08-26 15:27:02 +04:00
}
}
2008-09-12 06:59:59 +04:00
hw_dbg ( hw , " ixgbe_update_uc_addr_list_generic Complete \n " ) ;
2008-08-26 15:27:02 +04:00
return 0 ;
}
2007-09-16 01:07:45 +04:00
/**
* ixgbe_mta_vector - Determines bit - vector in multicast table to set
* @ hw : pointer to hardware structure
* @ mc_addr : the multicast address
*
* Extracts the 12 bits , from a multicast address , to determine which
* bit - vector to set in the multicast table . The hardware uses 12 bits , from
* incoming rx multicast addresses , to determine the bit - vector to check in
* the MTA . Which of the 4 combination , of 12 - bits , the hardware uses is set
2008-09-12 06:59:59 +04:00
* by the MO field of the MCSTCTRL . The MO field is set during initialization
2007-09-16 01:07:45 +04:00
* to mc_filter_type .
* */
static s32 ixgbe_mta_vector ( struct ixgbe_hw * hw , u8 * mc_addr )
{
u32 vector = 0 ;
switch ( hw - > mac . mc_filter_type ) {
2008-09-12 07:04:46 +04:00
case 0 : /* use bits [47:36] of the address */
2007-09-16 01:07:45 +04:00
vector = ( ( mc_addr [ 4 ] > > 4 ) | ( ( ( u16 ) mc_addr [ 5 ] ) < < 4 ) ) ;
break ;
2008-09-12 07:04:46 +04:00
case 1 : /* use bits [46:35] of the address */
2007-09-16 01:07:45 +04:00
vector = ( ( mc_addr [ 4 ] > > 3 ) | ( ( ( u16 ) mc_addr [ 5 ] ) < < 5 ) ) ;
break ;
2008-09-12 07:04:46 +04:00
case 2 : /* use bits [45:34] of the address */
2007-09-16 01:07:45 +04:00
vector = ( ( mc_addr [ 4 ] > > 2 ) | ( ( ( u16 ) mc_addr [ 5 ] ) < < 6 ) ) ;
break ;
2008-09-12 07:04:46 +04:00
case 3 : /* use bits [43:32] of the address */
2007-09-16 01:07:45 +04:00
vector = ( ( mc_addr [ 4 ] ) | ( ( ( u16 ) mc_addr [ 5 ] ) < < 8 ) ) ;
break ;
2008-09-12 07:04:46 +04:00
default : /* Invalid mc_filter_type */
2007-09-16 01:07:45 +04:00
hw_dbg ( hw , " MC filter type param set incorrectly \n " ) ;
break ;
}
/* vector can only be 12-bits or boundary will be exceeded */
vector & = 0xFFF ;
return vector ;
}
/**
* ixgbe_set_mta - Set bit - vector in multicast table
* @ hw : pointer to hardware structure
* @ hash_value : Multicast address hash value
*
* Sets the bit - vector in the multicast table .
* */
static void ixgbe_set_mta ( struct ixgbe_hw * hw , u8 * mc_addr )
{
u32 vector ;
u32 vector_bit ;
u32 vector_reg ;
u32 mta_reg ;
hw - > addr_ctrl . mta_in_use + + ;
vector = ixgbe_mta_vector ( hw , mc_addr ) ;
hw_dbg ( hw , " bit-vector = 0x%03X \n " , vector ) ;
/*
* The MTA is a register array of 128 32 - bit registers . It is treated
* like an array of 4096 bits . We want to set bit
* BitArray [ vector_value ] . So we figure out what register the bit is
* in , read it , OR in the new bit , then write back the new value . The
* register is determined by the upper 7 bits of the vector value and
* the bit within that register are determined by the lower 5 bits of
* the value .
*/
vector_reg = ( vector > > 5 ) & 0x7F ;
vector_bit = vector & 0x1F ;
mta_reg = IXGBE_READ_REG ( hw , IXGBE_MTA ( vector_reg ) ) ;
mta_reg | = ( 1 < < vector_bit ) ;
IXGBE_WRITE_REG ( hw , IXGBE_MTA ( vector_reg ) , mta_reg ) ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
2010-03-24 01:58:01 +03:00
* @ netdev : pointer to net device structure
2007-09-16 01:07:45 +04:00
*
* The given list replaces any existing list . Clears the MC addrs from receive
2008-09-12 06:59:59 +04:00
* address registers and the multicast table . Uses unused receive address
2007-09-16 01:07:45 +04:00
* registers for the first multicast addresses , and hashes the rest into the
* multicast table .
* */
2010-03-24 01:58:01 +03:00
s32 ixgbe_update_mc_addr_list_generic ( struct ixgbe_hw * hw ,
struct net_device * netdev )
2007-09-16 01:07:45 +04:00
{
2010-04-02 01:22:57 +04:00
struct netdev_hw_addr * ha ;
2007-09-16 01:07:45 +04:00
u32 i ;
/*
* Set the new number of MC addresses that we are being requested to
* use .
*/
2010-03-24 01:58:01 +03:00
hw - > addr_ctrl . num_mc_addrs = netdev_mc_count ( netdev ) ;
2007-09-16 01:07:45 +04:00
hw - > addr_ctrl . mta_in_use = 0 ;
/* Clear the MTA */
hw_dbg ( hw , " Clearing MTA \n " ) ;
2008-08-26 15:27:02 +04:00
for ( i = 0 ; i < hw - > mac . mcft_size ; i + + )
2007-09-16 01:07:45 +04:00
IXGBE_WRITE_REG ( hw , IXGBE_MTA ( i ) , 0 ) ;
/* Add the new addresses */
2010-04-02 01:22:57 +04:00
netdev_for_each_mc_addr ( ha , netdev ) {
2007-09-16 01:07:45 +04:00
hw_dbg ( hw , " Adding the multicast addresses: \n " ) ;
2010-04-02 01:22:57 +04:00
ixgbe_set_mta ( hw , ha - > addr ) ;
2007-09-16 01:07:45 +04:00
}
/* Enable mta */
if ( hw - > addr_ctrl . mta_in_use > 0 )
IXGBE_WRITE_REG ( hw , IXGBE_MCSTCTRL ,
2008-09-12 07:04:46 +04:00
IXGBE_MCSTCTRL_MFE | hw - > mac . mc_filter_type ) ;
2007-09-16 01:07:45 +04:00
2008-09-12 06:59:59 +04:00
hw_dbg ( hw , " ixgbe_update_mc_addr_list_generic Complete \n " ) ;
2007-09-16 01:07:45 +04:00
return 0 ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_enable_mc_generic - Enable multicast address in RAR
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
*
2008-09-12 06:59:59 +04:00
* Enables multicast address in RAR and the use of the multicast hash table .
2007-09-16 01:07:45 +04:00
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_enable_mc_generic ( struct ixgbe_hw * hw )
2007-09-16 01:07:45 +04:00
{
2008-09-12 06:59:59 +04:00
u32 i ;
u32 rar_entries = hw - > mac . num_rar_entries ;
struct ixgbe_addr_filter_info * a = & hw - > addr_ctrl ;
2007-09-16 01:07:45 +04:00
2008-09-12 06:59:59 +04:00
if ( a - > mc_addr_in_rar_count > 0 )
for ( i = ( rar_entries - a - > mc_addr_in_rar_count ) ;
i < rar_entries ; i + + )
ixgbe_enable_rar ( hw , i ) ;
2007-09-16 01:07:45 +04:00
2008-09-12 06:59:59 +04:00
if ( a - > mta_in_use > 0 )
IXGBE_WRITE_REG ( hw , IXGBE_MCSTCTRL , IXGBE_MCSTCTRL_MFE |
hw - > mac . mc_filter_type ) ;
2007-09-16 01:07:45 +04:00
return 0 ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_disable_mc_generic - Disable multicast address in RAR
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
*
2008-09-12 06:59:59 +04:00
* Disables multicast address in RAR and the use of the multicast hash table .
2007-09-16 01:07:45 +04:00
* */
2008-09-12 06:59:59 +04:00
s32 ixgbe_disable_mc_generic ( struct ixgbe_hw * hw )
2007-09-16 01:07:45 +04:00
{
2008-09-12 06:59:59 +04:00
u32 i ;
u32 rar_entries = hw - > mac . num_rar_entries ;
struct ixgbe_addr_filter_info * a = & hw - > addr_ctrl ;
2008-08-26 15:27:10 +04:00
2008-09-12 06:59:59 +04:00
if ( a - > mc_addr_in_rar_count > 0 )
for ( i = ( rar_entries - a - > mc_addr_in_rar_count ) ;
i < rar_entries ; i + + )
ixgbe_disable_rar ( hw , i ) ;
2007-09-16 01:07:45 +04:00
2008-09-12 06:59:59 +04:00
if ( a - > mta_in_use > 0 )
IXGBE_WRITE_REG ( hw , IXGBE_MCSTCTRL , hw - > mac . mc_filter_type ) ;
2007-09-16 01:07:45 +04:00
return 0 ;
}
2009-02-27 18:44:30 +03:00
/**
2009-06-04 15:11:13 +04:00
* ixgbe_fc_enable_generic - Enable flow control
2009-02-27 18:44:30 +03:00
* @ hw : pointer to hardware structure
* @ packetbuf_num : packet buffer number ( 0 - 7 )
*
* Enable flow control according to the current settings .
* */
2009-06-04 15:11:13 +04:00
s32 ixgbe_fc_enable_generic ( struct ixgbe_hw * hw , s32 packetbuf_num )
2009-02-27 18:44:30 +03:00
{
s32 ret_val = 0 ;
2009-06-04 15:11:13 +04:00
u32 mflcn_reg , fccfg_reg ;
2009-02-27 18:44:30 +03:00
u32 reg ;
2009-05-17 16:34:55 +04:00
u32 rx_pba_size ;
# ifdef CONFIG_DCB
if ( hw - > fc . requested_mode = = ixgbe_fc_pfc )
goto out ;
# endif /* CONFIG_DCB */
2009-06-04 15:11:13 +04:00
/* Negotiate the fc mode to use */
ret_val = ixgbe_fc_autoneg ( hw ) ;
if ( ret_val )
goto out ;
2009-02-27 18:44:30 +03:00
2009-06-04 15:11:13 +04:00
/* Disable any previous flow control settings */
2009-02-27 18:44:30 +03:00
mflcn_reg = IXGBE_READ_REG ( hw , IXGBE_MFLCN ) ;
mflcn_reg & = ~ ( IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE ) ;
fccfg_reg = IXGBE_READ_REG ( hw , IXGBE_FCCFG ) ;
fccfg_reg & = ~ ( IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY ) ;
/*
* The possible values of fc . current_mode are :
* 0 : Flow control is completely disabled
* 1 : Rx flow control is enabled ( we can receive pause frames ,
* but not send pause frames ) .
2009-03-26 01:10:42 +03:00
* 2 : Tx flow control is enabled ( we can send pause frames but
* we do not support receiving pause frames ) .
2009-02-27 18:44:30 +03:00
* 3 : Both Rx and Tx flow control ( symmetric ) are enabled .
2009-03-26 01:10:42 +03:00
* 4 : Priority Flow Control is enabled .
2009-02-27 18:44:30 +03:00
* other : Invalid .
*/
switch ( hw - > fc . current_mode ) {
case ixgbe_fc_none :
2009-06-04 15:11:13 +04:00
/*
* Flow control is disabled by software override or autoneg .
* The code below will actually disable it in the HW .
*/
2009-02-27 18:44:30 +03:00
break ;
case ixgbe_fc_rx_pause :
/*
* Rx Flow control is enabled and Tx Flow control is
* disabled by software override . Since there really
* isn ' t a way to advertise that we are capable of RX
* Pause ONLY , we will advertise that we support both
* symmetric and asymmetric Rx PAUSE . Later , we will
* disable the adapter ' s ability to send PAUSE frames .
*/
mflcn_reg | = IXGBE_MFLCN_RFCE ;
break ;
case ixgbe_fc_tx_pause :
/*
* Tx Flow control is enabled , and Rx Flow control is
* disabled by software override .
*/
fccfg_reg | = IXGBE_FCCFG_TFCE_802_3X ;
break ;
case ixgbe_fc_full :
/* Flow control (both Rx and Tx) is enabled by SW override. */
mflcn_reg | = IXGBE_MFLCN_RFCE ;
fccfg_reg | = IXGBE_FCCFG_TFCE_802_3X ;
break ;
2009-03-26 01:10:42 +03:00
# ifdef CONFIG_DCB
case ixgbe_fc_pfc :
goto out ;
break ;
2009-06-04 15:11:13 +04:00
# endif /* CONFIG_DCB */
2009-02-27 18:44:30 +03:00
default :
hw_dbg ( hw , " Flow control param set incorrectly \n " ) ;
2009-09-30 16:07:38 +04:00
ret_val = IXGBE_ERR_CONFIG ;
2009-02-27 18:44:30 +03:00
goto out ;
break ;
}
2009-06-04 15:11:13 +04:00
/* Set 802.3x based flow control settings. */
2009-04-10 02:26:21 +04:00
mflcn_reg | = IXGBE_MFLCN_DPF ;
2009-02-27 18:44:30 +03:00
IXGBE_WRITE_REG ( hw , IXGBE_MFLCN , mflcn_reg ) ;
IXGBE_WRITE_REG ( hw , IXGBE_FCCFG , fccfg_reg ) ;
2009-05-17 16:34:55 +04:00
reg = IXGBE_READ_REG ( hw , IXGBE_MTQC ) ;
/* Thresholds are different for link flow control when in DCB mode */
if ( reg & IXGBE_MTQC_RT_ENA ) {
2009-06-04 15:11:13 +04:00
rx_pba_size = IXGBE_READ_REG ( hw , IXGBE_RXPBSIZE ( packetbuf_num ) ) ;
2009-05-17 16:34:55 +04:00
/* Always disable XON for LFC when in DCB mode */
2009-06-04 15:11:13 +04:00
reg = ( rx_pba_size > > 5 ) & 0xFFE0 ;
IXGBE_WRITE_REG ( hw , IXGBE_FCRTL_82599 ( packetbuf_num ) , reg ) ;
2009-05-17 16:35:16 +04:00
2009-05-17 16:34:55 +04:00
reg = ( rx_pba_size > > 2 ) & 0xFFE0 ;
if ( hw - > fc . current_mode & ixgbe_fc_tx_pause )
reg | = IXGBE_FCRTH_FCEN ;
IXGBE_WRITE_REG ( hw , IXGBE_FCRTH_82599 ( packetbuf_num ) , reg ) ;
} else {
/*
* Set up and enable Rx high / low water mark thresholds ,
* enable XON .
*/
if ( hw - > fc . current_mode & ixgbe_fc_tx_pause ) {
if ( hw - > fc . send_xon ) {
IXGBE_WRITE_REG ( hw ,
IXGBE_FCRTL_82599 ( packetbuf_num ) ,
( hw - > fc . low_water |
IXGBE_FCRTL_XONE ) ) ;
} else {
IXGBE_WRITE_REG ( hw ,
IXGBE_FCRTL_82599 ( packetbuf_num ) ,
hw - > fc . low_water ) ;
}
IXGBE_WRITE_REG ( hw , IXGBE_FCRTH_82599 ( packetbuf_num ) ,
( hw - > fc . high_water | IXGBE_FCRTH_FCEN ) ) ;
}
2009-02-27 18:44:30 +03:00
}
/* Configure pause time (2 TCs per register) */
2009-05-17 16:34:55 +04:00
reg = IXGBE_READ_REG ( hw , IXGBE_FCTTV ( packetbuf_num / 2 ) ) ;
2009-02-27 18:44:30 +03:00
if ( ( packetbuf_num & 1 ) = = 0 )
reg = ( reg & 0xFFFF0000 ) | hw - > fc . pause_time ;
else
reg = ( reg & 0x0000FFFF ) | ( hw - > fc . pause_time < < 16 ) ;
IXGBE_WRITE_REG ( hw , IXGBE_FCTTV ( packetbuf_num / 2 ) , reg ) ;
IXGBE_WRITE_REG ( hw , IXGBE_FCRTV , ( hw - > fc . pause_time > > 1 ) ) ;
out :
return ret_val ;
}
2009-02-07 08:46:54 +03:00
/**
* ixgbe_fc_autoneg - Configure flow control
* @ hw : pointer to hardware structure
*
2009-06-04 15:11:13 +04:00
* Compares our advertised flow control capabilities to those advertised by
* our link partner , and determines the proper flow control mode to use .
2009-02-07 08:46:54 +03:00
* */
s32 ixgbe_fc_autoneg ( struct ixgbe_hw * hw )
{
s32 ret_val = 0 ;
2009-06-04 15:11:13 +04:00
ixgbe_link_speed speed ;
u32 pcs_anadv_reg , pcs_lpab_reg , linkstat ;
2009-09-30 16:07:38 +04:00
u32 links2 , anlp1_reg , autoc_reg , links ;
2009-06-04 15:11:13 +04:00
bool link_up ;
2009-02-07 08:46:54 +03:00
/*
2009-06-04 15:11:13 +04:00
* AN should have completed when the cable was plugged in .
* Look for reasons to bail out . Bail out if :
* - FC autoneg is disabled , or if
2009-09-30 16:07:38 +04:00
* - link is not up .
2009-06-04 15:11:13 +04:00
*
2009-09-30 16:07:38 +04:00
* Since we ' re being called from an LSC , link is already known to be up .
2009-06-04 15:11:13 +04:00
* So use link_up_wait_to_complete = false .
2009-02-07 08:46:54 +03:00
*/
2009-06-04 15:11:13 +04:00
hw - > mac . ops . check_link ( hw , & speed , & link_up , false ) ;
2009-09-30 16:07:38 +04:00
if ( hw - > fc . disable_fc_autoneg | | ( ! link_up ) ) {
2009-06-04 15:11:13 +04:00
hw - > fc . fc_was_autonegged = false ;
hw - > fc . current_mode = hw - > fc . requested_mode ;
2009-02-07 08:46:54 +03:00
goto out ;
}
2009-09-30 16:07:38 +04:00
/*
* On backplane , bail out if
* - backplane autoneg was not completed , or if
2009-11-24 21:51:48 +03:00
* - we are 82599 and link partner is not AN enabled
2009-09-30 16:07:38 +04:00
*/
if ( hw - > phy . media_type = = ixgbe_media_type_backplane ) {
links = IXGBE_READ_REG ( hw , IXGBE_LINKS ) ;
2009-11-24 21:51:48 +03:00
if ( ( links & IXGBE_LINKS_KX_AN_COMP ) = = 0 ) {
2009-09-30 16:07:38 +04:00
hw - > fc . fc_was_autonegged = false ;
hw - > fc . current_mode = hw - > fc . requested_mode ;
goto out ;
}
2009-11-24 21:51:48 +03:00
if ( hw - > mac . type = = ixgbe_mac_82599EB ) {
links2 = IXGBE_READ_REG ( hw , IXGBE_LINKS2 ) ;
if ( ( links2 & IXGBE_LINKS2_AN_SUPPORTED ) = = 0 ) {
hw - > fc . fc_was_autonegged = false ;
hw - > fc . current_mode = hw - > fc . requested_mode ;
goto out ;
}
}
2009-09-30 16:07:38 +04:00
}
/*
* On multispeed fiber at 1 g , bail out if
* - link is up but AN did not complete , or if
* - link is up and AN completed but timed out
*/
if ( hw - > phy . multispeed_fiber & & ( speed = = IXGBE_LINK_SPEED_1GB_FULL ) ) {
linkstat = IXGBE_READ_REG ( hw , IXGBE_PCS1GLSTA ) ;
if ( ( ( linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE ) = = 0 ) | |
( ( linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT ) = = 1 ) ) {
hw - > fc . fc_was_autonegged = false ;
hw - > fc . current_mode = hw - > fc . requested_mode ;
goto out ;
}
}
2009-11-24 21:51:28 +03:00
/*
* Bail out on
* - copper or CX4 adapters
* - fiber adapters running at 10 gig
*/
if ( ( hw - > phy . media_type = = ixgbe_media_type_copper ) | |
( hw - > phy . media_type = = ixgbe_media_type_cx4 ) | |
( ( hw - > phy . media_type = = ixgbe_media_type_fiber ) & &
( speed = = IXGBE_LINK_SPEED_10GB_FULL ) ) ) {
hw - > fc . fc_was_autonegged = false ;
hw - > fc . current_mode = hw - > fc . requested_mode ;
goto out ;
}
2009-02-07 08:46:54 +03:00
/*
* Read the AN advertisement and LP ability registers and resolve
* local flow control settings accordingly
*/
2009-09-30 16:07:38 +04:00
if ( ( speed = = IXGBE_LINK_SPEED_1GB_FULL ) & &
( hw - > phy . media_type ! = ixgbe_media_type_backplane ) ) {
pcs_anadv_reg = IXGBE_READ_REG ( hw , IXGBE_PCS1GANA ) ;
pcs_lpab_reg = IXGBE_READ_REG ( hw , IXGBE_PCS1GANLP ) ;
if ( ( pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE ) & &
( pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE ) ) {
/*
* Now we need to check if the user selected Rx ONLY
* of pause frames . In this case , we had to advertise
* FULL flow control because we could not advertise RX
* ONLY . Hence , we must now check to see if we need to
* turn OFF the TRANSMISSION of PAUSE frames .
*/
if ( hw - > fc . requested_mode = = ixgbe_fc_full ) {
hw - > fc . current_mode = ixgbe_fc_full ;
hw_dbg ( hw , " Flow Control = FULL. \n " ) ;
} else {
hw - > fc . current_mode = ixgbe_fc_rx_pause ;
hw_dbg ( hw , " Flow Control=RX PAUSE only \n " ) ;
}
} else if ( ! ( pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE ) & &
( pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE ) & &
( pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE ) & &
( pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE ) ) {
hw - > fc . current_mode = ixgbe_fc_tx_pause ;
hw_dbg ( hw , " Flow Control = TX PAUSE frames only. \n " ) ;
} else if ( ( pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE ) & &
( pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE ) & &
! ( pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE ) & &
( pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE ) ) {
hw - > fc . current_mode = ixgbe_fc_rx_pause ;
hw_dbg ( hw , " Flow Control = RX PAUSE frames only. \n " ) ;
} else {
hw - > fc . current_mode = ixgbe_fc_none ;
hw_dbg ( hw , " Flow Control = NONE. \n " ) ;
}
}
if ( hw - > phy . media_type = = ixgbe_media_type_backplane ) {
2009-02-07 08:46:54 +03:00
/*
2009-09-30 16:07:38 +04:00
* Read the 10 g AN autoc and LP ability registers and resolve
* local flow control settings accordingly
2009-02-07 08:46:54 +03:00
*/
2009-09-30 16:07:38 +04:00
autoc_reg = IXGBE_READ_REG ( hw , IXGBE_AUTOC ) ;
anlp1_reg = IXGBE_READ_REG ( hw , IXGBE_ANLP1 ) ;
if ( ( autoc_reg & IXGBE_AUTOC_SYM_PAUSE ) & &
( anlp1_reg & IXGBE_ANLP1_SYM_PAUSE ) ) {
/*
* Now we need to check if the user selected Rx ONLY
* of pause frames . In this case , we had to advertise
* FULL flow control because we could not advertise RX
* ONLY . Hence , we must now check to see if we need to
* turn OFF the TRANSMISSION of PAUSE frames .
*/
if ( hw - > fc . requested_mode = = ixgbe_fc_full ) {
hw - > fc . current_mode = ixgbe_fc_full ;
hw_dbg ( hw , " Flow Control = FULL. \n " ) ;
} else {
hw - > fc . current_mode = ixgbe_fc_rx_pause ;
hw_dbg ( hw , " Flow Control=RX PAUSE only \n " ) ;
}
} else if ( ! ( autoc_reg & IXGBE_AUTOC_SYM_PAUSE ) & &
( autoc_reg & IXGBE_AUTOC_ASM_PAUSE ) & &
( anlp1_reg & IXGBE_ANLP1_SYM_PAUSE ) & &
( anlp1_reg & IXGBE_ANLP1_ASM_PAUSE ) ) {
hw - > fc . current_mode = ixgbe_fc_tx_pause ;
hw_dbg ( hw , " Flow Control = TX PAUSE frames only. \n " ) ;
} else if ( ( autoc_reg & IXGBE_AUTOC_SYM_PAUSE ) & &
( autoc_reg & IXGBE_AUTOC_ASM_PAUSE ) & &
! ( anlp1_reg & IXGBE_ANLP1_SYM_PAUSE ) & &
( anlp1_reg & IXGBE_ANLP1_ASM_PAUSE ) ) {
2009-02-07 08:46:54 +03:00
hw - > fc . current_mode = ixgbe_fc_rx_pause ;
hw_dbg ( hw , " Flow Control = RX PAUSE frames only. \n " ) ;
2009-09-30 16:07:38 +04:00
} else {
hw - > fc . current_mode = ixgbe_fc_none ;
hw_dbg ( hw , " Flow Control = NONE. \n " ) ;
2009-02-07 08:46:54 +03:00
}
}
2009-06-04 15:11:13 +04:00
/* Record that current_mode is the result of a successful autoneg */
hw - > fc . fc_was_autonegged = true ;
2009-02-07 08:46:54 +03:00
out :
return ret_val ;
}
2009-02-27 18:44:30 +03:00
/**
2009-06-04 15:11:13 +04:00
* ixgbe_setup_fc - Set up flow control
2009-02-27 18:44:30 +03:00
* @ hw : pointer to hardware structure
*
2009-06-04 15:11:13 +04:00
* Called at init time to set up flow control .
2009-02-27 18:44:30 +03:00
* */
2009-08-25 08:47:32 +04:00
static s32 ixgbe_setup_fc ( struct ixgbe_hw * hw , s32 packetbuf_num )
2009-02-27 18:44:30 +03:00
{
s32 ret_val = 0 ;
2009-06-04 15:11:13 +04:00
u32 reg ;
2009-02-27 18:44:30 +03:00
2009-03-26 01:10:42 +03:00
# ifdef CONFIG_DCB
if ( hw - > fc . requested_mode = = ixgbe_fc_pfc ) {
hw - > fc . current_mode = hw - > fc . requested_mode ;
goto out ;
}
# endif
2009-02-27 18:44:30 +03:00
/* Validate the packetbuf configuration */
if ( packetbuf_num < 0 | | packetbuf_num > 7 ) {
hw_dbg ( hw , " Invalid packet buffer number [%d], expected range "
" is 0-7 \n " , packetbuf_num ) ;
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS ;
goto out ;
}
/*
* Validate the water mark configuration . Zero water marks are invalid
* because it causes the controller to just blast out fc packets .
*/
if ( ! hw - > fc . low_water | | ! hw - > fc . high_water | | ! hw - > fc . pause_time ) {
2009-06-04 15:11:13 +04:00
hw_dbg ( hw , " Invalid water mark configuration \n " ) ;
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS ;
goto out ;
2009-02-27 18:44:30 +03:00
}
/*
* Validate the requested mode . Strict IEEE mode does not allow
2009-06-04 15:11:13 +04:00
* ixgbe_fc_rx_pause because it will cause us to fail at UNH .
2009-02-27 18:44:30 +03:00
*/
if ( hw - > fc . strict_ieee & & hw - > fc . requested_mode = = ixgbe_fc_rx_pause ) {
hw_dbg ( hw , " ixgbe_fc_rx_pause not valid in strict "
" IEEE mode \n " ) ;
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS ;
goto out ;
}
/*
* 10 gig parts do not have a word in the EEPROM to determine the
* default flow control setting , so we explicitly set it to full .
*/
if ( hw - > fc . requested_mode = = ixgbe_fc_default )
hw - > fc . requested_mode = ixgbe_fc_full ;
/*
2009-06-04 15:11:13 +04:00
* Set up the 1 G flow control advertisement registers so the HW will be
* able to do fc autoneg once the cable is plugged in . If we end up
* using 10 g instead , this is harmless .
2009-02-27 18:44:30 +03:00
*/
2009-06-04 15:11:13 +04:00
reg = IXGBE_READ_REG ( hw , IXGBE_PCS1GANA ) ;
2009-02-27 18:44:30 +03:00
2009-06-04 15:11:13 +04:00
/*
* The possible values of fc . requested_mode are :
* 0 : Flow control is completely disabled
* 1 : Rx flow control is enabled ( we can receive pause frames ,
* but not send pause frames ) .
* 2 : Tx flow control is enabled ( we can send pause frames but
* we do not support receiving pause frames ) .
* 3 : Both Rx and Tx flow control ( symmetric ) are enabled .
# ifdef CONFIG_DCB
* 4 : Priority Flow Control is enabled .
# endif
* other : Invalid .
*/
switch ( hw - > fc . requested_mode ) {
case ixgbe_fc_none :
/* Flow control completely disabled by software override. */
reg & = ~ ( IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE ) ;
break ;
case ixgbe_fc_rx_pause :
/*
* Rx Flow control is enabled and Tx Flow control is
* disabled by software override . Since there really
* isn ' t a way to advertise that we are capable of RX
* Pause ONLY , we will advertise that we support both
* symmetric and asymmetric Rx PAUSE . Later , we will
* disable the adapter ' s ability to send PAUSE frames .
*/
reg | = ( IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE ) ;
break ;
case ixgbe_fc_tx_pause :
/*
* Tx Flow control is enabled , and Rx Flow control is
* disabled by software override .
*/
reg | = ( IXGBE_PCS1GANA_ASM_PAUSE ) ;
reg & = ~ ( IXGBE_PCS1GANA_SYM_PAUSE ) ;
break ;
case ixgbe_fc_full :
/* Flow control (both Rx and Tx) is enabled by SW override. */
reg | = ( IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE ) ;
break ;
# ifdef CONFIG_DCB
case ixgbe_fc_pfc :
2009-02-27 18:44:30 +03:00
goto out ;
2009-06-04 15:11:13 +04:00
break ;
# endif /* CONFIG_DCB */
default :
hw_dbg ( hw , " Flow control param set incorrectly \n " ) ;
2009-09-30 16:07:38 +04:00
ret_val = IXGBE_ERR_CONFIG ;
2009-06-04 15:11:13 +04:00
goto out ;
break ;
}
IXGBE_WRITE_REG ( hw , IXGBE_PCS1GANA , reg ) ;
reg = IXGBE_READ_REG ( hw , IXGBE_PCS1GLCTL ) ;
2009-02-27 18:44:30 +03:00
2009-06-04 15:11:13 +04:00
/* Disable AN timeout */
if ( hw - > fc . strict_ieee )
reg & = ~ IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN ;
IXGBE_WRITE_REG ( hw , IXGBE_PCS1GLCTL , reg ) ;
hw_dbg ( hw , " Set up FC; PCS1GLCTL = 0x%08X \n " , reg ) ;
2009-02-27 18:44:30 +03:00
2009-09-30 16:07:38 +04:00
/*
* Set up the 10 G flow control advertisement registers so the HW
* can do fc autoneg once the cable is plugged in . If we end up
* using 1 g instead , this is harmless .
*/
reg = IXGBE_READ_REG ( hw , IXGBE_AUTOC ) ;
/*
* The possible values of fc . requested_mode are :
* 0 : Flow control is completely disabled
* 1 : Rx flow control is enabled ( we can receive pause frames ,
* but not send pause frames ) .
* 2 : Tx flow control is enabled ( we can send pause frames but
* we do not support receiving pause frames ) .
* 3 : Both Rx and Tx flow control ( symmetric ) are enabled .
* other : Invalid .
*/
switch ( hw - > fc . requested_mode ) {
case ixgbe_fc_none :
/* Flow control completely disabled by software override. */
reg & = ~ ( IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE ) ;
break ;
case ixgbe_fc_rx_pause :
/*
* Rx Flow control is enabled and Tx Flow control is
* disabled by software override . Since there really
* isn ' t a way to advertise that we are capable of RX
* Pause ONLY , we will advertise that we support both
* symmetric and asymmetric Rx PAUSE . Later , we will
* disable the adapter ' s ability to send PAUSE frames .
*/
reg | = ( IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE ) ;
break ;
case ixgbe_fc_tx_pause :
/*
* Tx Flow control is enabled , and Rx Flow control is
* disabled by software override .
*/
reg | = ( IXGBE_AUTOC_ASM_PAUSE ) ;
reg & = ~ ( IXGBE_AUTOC_SYM_PAUSE ) ;
break ;
case ixgbe_fc_full :
/* Flow control (both Rx and Tx) is enabled by SW override. */
reg | = ( IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE ) ;
break ;
# ifdef CONFIG_DCB
case ixgbe_fc_pfc :
goto out ;
break ;
# endif /* CONFIG_DCB */
default :
hw_dbg ( hw , " Flow control param set incorrectly \n " ) ;
ret_val = IXGBE_ERR_CONFIG ;
goto out ;
break ;
}
/*
* AUTOC restart handles negotiation of 1 G and 10 G . There is
* no need to set the PCS1GCTL register .
*/
reg | = IXGBE_AUTOC_AN_RESTART ;
IXGBE_WRITE_REG ( hw , IXGBE_AUTOC , reg ) ;
hw_dbg ( hw , " Set up FC; IXGBE_AUTOC = 0x%08X \n " , reg ) ;
2009-02-27 18:44:30 +03:00
out :
return ret_val ;
}
2007-09-16 01:07:45 +04:00
/**
* ixgbe_disable_pcie_master - Disable PCI - express master access
* @ hw : pointer to hardware structure
*
* Disables PCI - Express master access and verifies there are no pending
* requests . IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
* bit hasn ' t caused the master requests to be disabled , else 0
* is returned signifying master requests disabled .
* */
s32 ixgbe_disable_pcie_master ( struct ixgbe_hw * hw )
{
2008-09-12 06:59:59 +04:00
u32 i ;
u32 reg_val ;
u32 number_of_queues ;
2007-09-16 01:07:45 +04:00
s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING ;
2008-09-12 06:59:59 +04:00
/* Disable the receive unit by stopping each queue */
number_of_queues = hw - > mac . max_rx_queues ;
for ( i = 0 ; i < number_of_queues ; i + + ) {
reg_val = IXGBE_READ_REG ( hw , IXGBE_RXDCTL ( i ) ) ;
if ( reg_val & IXGBE_RXDCTL_ENABLE ) {
reg_val & = ~ IXGBE_RXDCTL_ENABLE ;
IXGBE_WRITE_REG ( hw , IXGBE_RXDCTL ( i ) , reg_val ) ;
}
}
reg_val = IXGBE_READ_REG ( hw , IXGBE_CTRL ) ;
reg_val | = IXGBE_CTRL_GIO_DIS ;
IXGBE_WRITE_REG ( hw , IXGBE_CTRL , reg_val ) ;
2007-09-16 01:07:45 +04:00
for ( i = 0 ; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT ; i + + ) {
if ( ! ( IXGBE_READ_REG ( hw , IXGBE_STATUS ) & IXGBE_STATUS_GIO ) ) {
status = 0 ;
break ;
}
udelay ( 100 ) ;
}
return status ;
}
/**
2008-09-12 06:59:59 +04:00
* ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
2007-09-16 01:07:45 +04:00
* @ hw : pointer to hardware structure
2008-09-12 06:59:59 +04:00
* @ mask : Mask to specify which semaphore to acquire
2007-09-16 01:07:45 +04:00
*
2008-09-12 06:59:59 +04:00
* Acquires the SWFW semaphore thought the GSSR register for the specified
2007-09-16 01:07:45 +04:00
* function ( CSR , PHY0 , PHY1 , EEPROM , Flash )
* */
s32 ixgbe_acquire_swfw_sync ( struct ixgbe_hw * hw , u16 mask )
{
u32 gssr ;
u32 swmask = mask ;
u32 fwmask = mask < < 5 ;
s32 timeout = 200 ;
while ( timeout ) {
if ( ixgbe_get_eeprom_semaphore ( hw ) )
2009-09-30 16:07:38 +04:00
return IXGBE_ERR_SWFW_SYNC ;
2007-09-16 01:07:45 +04:00
gssr = IXGBE_READ_REG ( hw , IXGBE_GSSR ) ;
if ( ! ( gssr & ( fwmask | swmask ) ) )
break ;
/*
* Firmware currently using resource ( fwmask ) or other software
* thread currently using resource ( swmask )
*/
ixgbe_release_eeprom_semaphore ( hw ) ;
msleep ( 5 ) ;
timeout - - ;
}
if ( ! timeout ) {
hw_dbg ( hw , " Driver can't access resource, GSSR timeout. \n " ) ;
2009-09-30 16:07:38 +04:00
return IXGBE_ERR_SWFW_SYNC ;
2007-09-16 01:07:45 +04:00
}
gssr | = swmask ;
IXGBE_WRITE_REG ( hw , IXGBE_GSSR , gssr ) ;
ixgbe_release_eeprom_semaphore ( hw ) ;
return 0 ;
}
/**
* ixgbe_release_swfw_sync - Release SWFW semaphore
* @ hw : pointer to hardware structure
2008-09-12 06:59:59 +04:00
* @ mask : Mask to specify which semaphore to release
2007-09-16 01:07:45 +04:00
*
2008-09-12 06:59:59 +04:00
* Releases the SWFW semaphore thought the GSSR register for the specified
2007-09-16 01:07:45 +04:00
* function ( CSR , PHY0 , PHY1 , EEPROM , Flash )
* */
void ixgbe_release_swfw_sync ( struct ixgbe_hw * hw , u16 mask )
{
u32 gssr ;
u32 swmask = mask ;
ixgbe_get_eeprom_semaphore ( hw ) ;
gssr = IXGBE_READ_REG ( hw , IXGBE_GSSR ) ;
gssr & = ~ swmask ;
IXGBE_WRITE_REG ( hw , IXGBE_GSSR , gssr ) ;
ixgbe_release_eeprom_semaphore ( hw ) ;
}
2009-02-27 18:44:30 +03:00
/**
* ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
* @ hw : pointer to hardware structure
* @ regval : register value to write to RXCTRL
*
* Enables the Rx DMA unit
* */
s32 ixgbe_enable_rx_dma_generic ( struct ixgbe_hw * hw , u32 regval )
{
IXGBE_WRITE_REG ( hw , IXGBE_RXCTRL , regval ) ;
return 0 ;
}
2009-04-08 17:20:31 +04:00
/**
* ixgbe_blink_led_start_generic - Blink LED based on index .
* @ hw : pointer to hardware structure
* @ index : led number to blink
* */
s32 ixgbe_blink_led_start_generic ( struct ixgbe_hw * hw , u32 index )
{
ixgbe_link_speed speed = 0 ;
bool link_up = 0 ;
u32 autoc_reg = IXGBE_READ_REG ( hw , IXGBE_AUTOC ) ;
u32 led_reg = IXGBE_READ_REG ( hw , IXGBE_LEDCTL ) ;
/*
* Link must be up to auto - blink the LEDs ;
* Force it if link is down .
*/
hw - > mac . ops . check_link ( hw , & speed , & link_up , false ) ;
if ( ! link_up ) {
2009-06-04 15:10:53 +04:00
autoc_reg | = IXGBE_AUTOC_AN_RESTART ;
2009-04-08 17:20:31 +04:00
autoc_reg | = IXGBE_AUTOC_FLU ;
IXGBE_WRITE_REG ( hw , IXGBE_AUTOC , autoc_reg ) ;
msleep ( 10 ) ;
}
led_reg & = ~ IXGBE_LED_MODE_MASK ( index ) ;
led_reg | = IXGBE_LED_BLINK ( index ) ;
IXGBE_WRITE_REG ( hw , IXGBE_LEDCTL , led_reg ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
return 0 ;
}
/**
* ixgbe_blink_led_stop_generic - Stop blinking LED based on index .
* @ hw : pointer to hardware structure
* @ index : led number to stop blinking
* */
s32 ixgbe_blink_led_stop_generic ( struct ixgbe_hw * hw , u32 index )
{
u32 autoc_reg = IXGBE_READ_REG ( hw , IXGBE_AUTOC ) ;
u32 led_reg = IXGBE_READ_REG ( hw , IXGBE_LEDCTL ) ;
autoc_reg & = ~ IXGBE_AUTOC_FLU ;
autoc_reg | = IXGBE_AUTOC_AN_RESTART ;
IXGBE_WRITE_REG ( hw , IXGBE_AUTOC , autoc_reg ) ;
led_reg & = ~ IXGBE_LED_MODE_MASK ( index ) ;
led_reg & = ~ IXGBE_LED_BLINK ( index ) ;
led_reg | = IXGBE_LED_LINK_ACTIVE < < IXGBE_LED_MODE_SHIFT ( index ) ;
IXGBE_WRITE_REG ( hw , IXGBE_LEDCTL , led_reg ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
return 0 ;
}
2010-05-13 21:33:41 +04:00
/**
* ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM
* @ hw : pointer to hardware structure
* @ san_mac_offset : SAN MAC address offset
*
* This function will read the EEPROM location for the SAN MAC address
* pointer , and returns the value at that location . This is used in both
* get and set mac_addr routines .
* */
static s32 ixgbe_get_san_mac_addr_offset ( struct ixgbe_hw * hw ,
u16 * san_mac_offset )
{
/*
* First read the EEPROM pointer to see if the MAC addresses are
* available .
*/
hw - > eeprom . ops . read ( hw , IXGBE_SAN_MAC_ADDR_PTR , san_mac_offset ) ;
return 0 ;
}
/**
* ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM
* @ hw : pointer to hardware structure
* @ san_mac_addr : SAN MAC address
*
* Reads the SAN MAC address from the EEPROM , if it ' s available . This is
* per - port , so set_lan_id ( ) must be called before reading the addresses .
* set_lan_id ( ) is called by identify_sfp ( ) , but this cannot be relied
* upon for non - SFP connections , so we must call it here .
* */
s32 ixgbe_get_san_mac_addr_generic ( struct ixgbe_hw * hw , u8 * san_mac_addr )
{
u16 san_mac_data , san_mac_offset ;
u8 i ;
/*
* First read the EEPROM pointer to see if the MAC addresses are
* available . If they ' re not , no point in calling set_lan_id ( ) here .
*/
ixgbe_get_san_mac_addr_offset ( hw , & san_mac_offset ) ;
if ( ( san_mac_offset = = 0 ) | | ( san_mac_offset = = 0xFFFF ) ) {
/*
* No addresses available in this EEPROM . It ' s not an
* error though , so just wipe the local address and return .
*/
for ( i = 0 ; i < 6 ; i + + )
san_mac_addr [ i ] = 0xFF ;
goto san_mac_addr_out ;
}
/* make sure we know which port we need to program */
hw - > mac . ops . set_lan_id ( hw ) ;
/* apply the port offset to the address offset */
( hw - > bus . func ) ? ( san_mac_offset + = IXGBE_SAN_MAC_ADDR_PORT1_OFFSET ) :
( san_mac_offset + = IXGBE_SAN_MAC_ADDR_PORT0_OFFSET ) ;
for ( i = 0 ; i < 3 ; i + + ) {
hw - > eeprom . ops . read ( hw , san_mac_offset , & san_mac_data ) ;
san_mac_addr [ i * 2 ] = ( u8 ) ( san_mac_data ) ;
san_mac_addr [ i * 2 + 1 ] = ( u8 ) ( san_mac_data > > 8 ) ;
san_mac_offset + + ;
}
san_mac_addr_out :
return 0 ;
}
/**
* ixgbe_get_pcie_msix_count_generic - Gets MSI - X vector count
* @ hw : pointer to hardware structure
*
* Read PCIe configuration space , and get the MSI - X vector count from
* the capabilities table .
* */
u32 ixgbe_get_pcie_msix_count_generic ( struct ixgbe_hw * hw )
{
struct ixgbe_adapter * adapter = hw - > back ;
u16 msix_count ;
pci_read_config_word ( adapter - > pdev , IXGBE_PCIE_MSIX_82599_CAPS ,
& msix_count ) ;
msix_count & = IXGBE_PCIE_MSIX_TBL_SZ_MASK ;
/* MSI-X count is zero-based in HW, so increment to give proper value */
msix_count + + ;
return msix_count ;
}
/**
* ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address
* @ hw : pointer to hardware struct
* @ rar : receive address register index to disassociate
* @ vmdq : VMDq pool index to remove from the rar
* */
s32 ixgbe_clear_vmdq_generic ( struct ixgbe_hw * hw , u32 rar , u32 vmdq )
{
u32 mpsar_lo , mpsar_hi ;
u32 rar_entries = hw - > mac . num_rar_entries ;
if ( rar < rar_entries ) {
mpsar_lo = IXGBE_READ_REG ( hw , IXGBE_MPSAR_LO ( rar ) ) ;
mpsar_hi = IXGBE_READ_REG ( hw , IXGBE_MPSAR_HI ( rar ) ) ;
if ( ! mpsar_lo & & ! mpsar_hi )
goto done ;
if ( vmdq = = IXGBE_CLEAR_VMDQ_ALL ) {
if ( mpsar_lo ) {
IXGBE_WRITE_REG ( hw , IXGBE_MPSAR_LO ( rar ) , 0 ) ;
mpsar_lo = 0 ;
}
if ( mpsar_hi ) {
IXGBE_WRITE_REG ( hw , IXGBE_MPSAR_HI ( rar ) , 0 ) ;
mpsar_hi = 0 ;
}
} else if ( vmdq < 32 ) {
mpsar_lo & = ~ ( 1 < < vmdq ) ;
IXGBE_WRITE_REG ( hw , IXGBE_MPSAR_LO ( rar ) , mpsar_lo ) ;
} else {
mpsar_hi & = ~ ( 1 < < ( vmdq - 32 ) ) ;
IXGBE_WRITE_REG ( hw , IXGBE_MPSAR_HI ( rar ) , mpsar_hi ) ;
}
/* was that the last pool using this rar? */
if ( mpsar_lo = = 0 & & mpsar_hi = = 0 & & rar ! = 0 )
hw - > mac . ops . clear_rar ( hw , rar ) ;
} else {
hw_dbg ( hw , " RAR index %d is out of range. \n " , rar ) ;
}
done :
return 0 ;
}
/**
* ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address
* @ hw : pointer to hardware struct
* @ rar : receive address register index to associate with a VMDq index
* @ vmdq : VMDq pool index
* */
s32 ixgbe_set_vmdq_generic ( struct ixgbe_hw * hw , u32 rar , u32 vmdq )
{
u32 mpsar ;
u32 rar_entries = hw - > mac . num_rar_entries ;
if ( rar < rar_entries ) {
if ( vmdq < 32 ) {
mpsar = IXGBE_READ_REG ( hw , IXGBE_MPSAR_LO ( rar ) ) ;
mpsar | = 1 < < vmdq ;
IXGBE_WRITE_REG ( hw , IXGBE_MPSAR_LO ( rar ) , mpsar ) ;
} else {
mpsar = IXGBE_READ_REG ( hw , IXGBE_MPSAR_HI ( rar ) ) ;
mpsar | = 1 < < ( vmdq - 32 ) ;
IXGBE_WRITE_REG ( hw , IXGBE_MPSAR_HI ( rar ) , mpsar ) ;
}
} else {
hw_dbg ( hw , " RAR index %d is out of range. \n " , rar ) ;
}
return 0 ;
}
/**
* ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array
* @ hw : pointer to hardware structure
* */
s32 ixgbe_init_uta_tables_generic ( struct ixgbe_hw * hw )
{
int i ;
for ( i = 0 ; i < 128 ; i + + )
IXGBE_WRITE_REG ( hw , IXGBE_UTA ( i ) , 0 ) ;
return 0 ;
}
/**
* ixgbe_find_vlvf_slot - find the vlanid or the first empty slot
* @ hw : pointer to hardware structure
* @ vlan : VLAN id to write to VLAN filter
*
* return the VLVF index where this VLAN id should be placed
*
* */
s32 ixgbe_find_vlvf_slot ( struct ixgbe_hw * hw , u32 vlan )
{
u32 bits = 0 ;
u32 first_empty_slot = 0 ;
s32 regindex ;
/* short cut the special case */
if ( vlan = = 0 )
return 0 ;
/*
* Search for the vlan id in the VLVF entries . Save off the first empty
* slot found along the way
*/
for ( regindex = 1 ; regindex < IXGBE_VLVF_ENTRIES ; regindex + + ) {
bits = IXGBE_READ_REG ( hw , IXGBE_VLVF ( regindex ) ) ;
if ( ! bits & & ! ( first_empty_slot ) )
first_empty_slot = regindex ;
else if ( ( bits & 0x0FFF ) = = vlan )
break ;
}
/*
* If regindex is less than IXGBE_VLVF_ENTRIES , then we found the vlan
* in the VLVF . Else use the first empty VLVF register for this
* vlan id .
*/
if ( regindex > = IXGBE_VLVF_ENTRIES ) {
if ( first_empty_slot )
regindex = first_empty_slot ;
else {
hw_dbg ( hw , " No space in VLVF. \n " ) ;
regindex = IXGBE_ERR_NO_SPACE ;
}
}
return regindex ;
}
/**
* ixgbe_set_vfta_generic - Set VLAN filter table
* @ hw : pointer to hardware structure
* @ vlan : VLAN id to write to VLAN filter
* @ vind : VMDq output index that maps queue to VLAN id in VFVFB
* @ vlan_on : boolean flag to turn on / off VLAN in VFVF
*
* Turn on / off specified VLAN in the VLAN filter table .
* */
s32 ixgbe_set_vfta_generic ( struct ixgbe_hw * hw , u32 vlan , u32 vind ,
bool vlan_on )
{
s32 regindex ;
u32 bitindex ;
u32 vfta ;
u32 bits ;
u32 vt ;
u32 targetbit ;
bool vfta_changed = false ;
if ( vlan > 4095 )
return IXGBE_ERR_PARAM ;
/*
* this is a 2 part operation - first the VFTA , then the
* VLVF and VLVFB if VT Mode is set
* We don ' t write the VFTA until we know the VLVF part succeeded .
*/
/* Part 1
* The VFTA is a bitstring made up of 128 32 - bit registers
* that enable the particular VLAN id , much like the MTA :
* bits [ 11 - 5 ] : which register
* bits [ 4 - 0 ] : which bit in the register
*/
regindex = ( vlan > > 5 ) & 0x7F ;
bitindex = vlan & 0x1F ;
targetbit = ( 1 < < bitindex ) ;
vfta = IXGBE_READ_REG ( hw , IXGBE_VFTA ( regindex ) ) ;
if ( vlan_on ) {
if ( ! ( vfta & targetbit ) ) {
vfta | = targetbit ;
vfta_changed = true ;
}
} else {
if ( ( vfta & targetbit ) ) {
vfta & = ~ targetbit ;
vfta_changed = true ;
}
}
/* Part 2
* If VT Mode is set
* Either vlan_on
* make sure the vlan is in VLVF
* set the vind bit in the matching VLVFB
* Or ! vlan_on
* clear the pool bit and possibly the vind
*/
vt = IXGBE_READ_REG ( hw , IXGBE_VT_CTL ) ;
if ( vt & IXGBE_VT_CTL_VT_ENABLE ) {
s32 vlvf_index ;
vlvf_index = ixgbe_find_vlvf_slot ( hw , vlan ) ;
if ( vlvf_index < 0 )
return vlvf_index ;
if ( vlan_on ) {
/* set the pool bit */
if ( vind < 32 ) {
bits = IXGBE_READ_REG ( hw ,
IXGBE_VLVFB ( vlvf_index * 2 ) ) ;
bits | = ( 1 < < vind ) ;
IXGBE_WRITE_REG ( hw ,
IXGBE_VLVFB ( vlvf_index * 2 ) ,
bits ) ;
} else {
bits = IXGBE_READ_REG ( hw ,
IXGBE_VLVFB ( ( vlvf_index * 2 ) + 1 ) ) ;
bits | = ( 1 < < ( vind - 32 ) ) ;
IXGBE_WRITE_REG ( hw ,
IXGBE_VLVFB ( ( vlvf_index * 2 ) + 1 ) ,
bits ) ;
}
} else {
/* clear the pool bit */
if ( vind < 32 ) {
bits = IXGBE_READ_REG ( hw ,
IXGBE_VLVFB ( vlvf_index * 2 ) ) ;
bits & = ~ ( 1 < < vind ) ;
IXGBE_WRITE_REG ( hw ,
IXGBE_VLVFB ( vlvf_index * 2 ) ,
bits ) ;
bits | = IXGBE_READ_REG ( hw ,
IXGBE_VLVFB ( ( vlvf_index * 2 ) + 1 ) ) ;
} else {
bits = IXGBE_READ_REG ( hw ,
IXGBE_VLVFB ( ( vlvf_index * 2 ) + 1 ) ) ;
bits & = ~ ( 1 < < ( vind - 32 ) ) ;
IXGBE_WRITE_REG ( hw ,
IXGBE_VLVFB ( ( vlvf_index * 2 ) + 1 ) ,
bits ) ;
bits | = IXGBE_READ_REG ( hw ,
IXGBE_VLVFB ( vlvf_index * 2 ) ) ;
}
}
/*
* If there are still bits set in the VLVFB registers
* for the VLAN ID indicated we need to see if the
* caller is requesting that we clear the VFTA entry bit .
* If the caller has requested that we clear the VFTA
* entry bit but there are still pools / VFs using this VLAN
* ID entry then ignore the request . We ' re not worried
* about the case where we ' re turning the VFTA VLAN ID
* entry bit on , only when requested to turn it off as
* there may be multiple pools and / or VFs using the
* VLAN ID entry . In that case we cannot clear the
* VFTA bit until all pools / VFs using that VLAN ID have also
* been cleared . This will be indicated by " bits " being
* zero .
*/
if ( bits ) {
IXGBE_WRITE_REG ( hw , IXGBE_VLVF ( vlvf_index ) ,
( IXGBE_VLVF_VIEN | vlan ) ) ;
if ( ! vlan_on ) {
/* someone wants to clear the vfta entry
* but some pools / VFs are still using it .
* Ignore it . */
vfta_changed = false ;
}
}
else
IXGBE_WRITE_REG ( hw , IXGBE_VLVF ( vlvf_index ) , 0 ) ;
}
if ( vfta_changed )
IXGBE_WRITE_REG ( hw , IXGBE_VFTA ( regindex ) , vfta ) ;
return 0 ;
}
/**
* ixgbe_clear_vfta_generic - Clear VLAN filter table
* @ hw : pointer to hardware structure
*
* Clears the VLAN filer table , and the VMDq index associated with the filter
* */
s32 ixgbe_clear_vfta_generic ( struct ixgbe_hw * hw )
{
u32 offset ;
for ( offset = 0 ; offset < hw - > mac . vft_size ; offset + + )
IXGBE_WRITE_REG ( hw , IXGBE_VFTA ( offset ) , 0 ) ;
for ( offset = 0 ; offset < IXGBE_VLVF_ENTRIES ; offset + + ) {
IXGBE_WRITE_REG ( hw , IXGBE_VLVF ( offset ) , 0 ) ;
IXGBE_WRITE_REG ( hw , IXGBE_VLVFB ( offset * 2 ) , 0 ) ;
IXGBE_WRITE_REG ( hw , IXGBE_VLVFB ( ( offset * 2 ) + 1 ) , 0 ) ;
}
return 0 ;
}
/**
* ixgbe_check_mac_link_generic - Determine link and speed status
* @ hw : pointer to hardware structure
* @ speed : pointer to link speed
* @ link_up : true when link is up
* @ link_up_wait_to_complete : bool used to wait for link up or not
*
* Reads the links register to determine if link is up and the current speed
* */
s32 ixgbe_check_mac_link_generic ( struct ixgbe_hw * hw , ixgbe_link_speed * speed ,
bool * link_up , bool link_up_wait_to_complete )
{
u32 links_reg ;
u32 i ;
links_reg = IXGBE_READ_REG ( hw , IXGBE_LINKS ) ;
if ( link_up_wait_to_complete ) {
for ( i = 0 ; i < IXGBE_LINK_UP_TIME ; i + + ) {
if ( links_reg & IXGBE_LINKS_UP ) {
* link_up = true ;
break ;
} else {
* link_up = false ;
}
msleep ( 100 ) ;
links_reg = IXGBE_READ_REG ( hw , IXGBE_LINKS ) ;
}
} else {
if ( links_reg & IXGBE_LINKS_UP )
* link_up = true ;
else
* link_up = false ;
}
if ( ( links_reg & IXGBE_LINKS_SPEED_82599 ) = =
IXGBE_LINKS_SPEED_10G_82599 )
* speed = IXGBE_LINK_SPEED_10GB_FULL ;
else if ( ( links_reg & IXGBE_LINKS_SPEED_82599 ) = =
IXGBE_LINKS_SPEED_1G_82599 )
* speed = IXGBE_LINK_SPEED_1GB_FULL ;
else
* speed = IXGBE_LINK_SPEED_100_FULL ;
/* if link is down, zero out the current_mode */
if ( * link_up = = false ) {
hw - > fc . current_mode = ixgbe_fc_none ;
hw - > fc . fc_was_autonegged = false ;
}
return 0 ;
}
/**
* ixgbe_get_wwn_prefix_generic - Get alternative WWNN / WWPN prefix from
* the EEPROM
* @ hw : pointer to hardware structure
* @ wwnn_prefix : the alternative WWNN prefix
* @ wwpn_prefix : the alternative WWPN prefix
*
* This function will read the EEPROM from the alternative SAN MAC address
* block to check the support for the alternative WWNN / WWPN prefix support .
* */
s32 ixgbe_get_wwn_prefix_generic ( struct ixgbe_hw * hw , u16 * wwnn_prefix ,
u16 * wwpn_prefix )
{
u16 offset , caps ;
u16 alt_san_mac_blk_offset ;
/* clear output first */
* wwnn_prefix = 0xFFFF ;
* wwpn_prefix = 0xFFFF ;
/* check if alternative SAN MAC is supported */
hw - > eeprom . ops . read ( hw , IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR ,
& alt_san_mac_blk_offset ) ;
if ( ( alt_san_mac_blk_offset = = 0 ) | |
( alt_san_mac_blk_offset = = 0xFFFF ) )
goto wwn_prefix_out ;
/* check capability in alternative san mac address block */
offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET ;
hw - > eeprom . ops . read ( hw , offset , & caps ) ;
if ( ! ( caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN ) )
goto wwn_prefix_out ;
/* get the corresponding prefix for WWNN/WWPN */
offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET ;
hw - > eeprom . ops . read ( hw , offset , wwnn_prefix ) ;
offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET ;
hw - > eeprom . ops . read ( hw , offset , wwpn_prefix ) ;
wwn_prefix_out :
return 0 ;
}