2007-09-15 14:07:45 -07:00
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright ( c ) 1999 - 2007 Intel Corporation .
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 :
Linux NICS < linux . nics @ intel . com >
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>
# include "ixgbe_common.h"
# include "ixgbe_phy.h"
static s32 ixgbe_clear_hw_cntrs ( struct ixgbe_hw * hw ) ;
static s32 ixgbe_poll_eeprom_eerd_done ( struct ixgbe_hw * hw ) ;
static s32 ixgbe_get_eeprom_semaphore ( struct ixgbe_hw * hw ) ;
static void ixgbe_release_eeprom_semaphore ( struct ixgbe_hw * hw ) ;
static u16 ixgbe_calc_eeprom_checksum ( struct ixgbe_hw * hw ) ;
static s32 ixgbe_clear_vfta ( struct ixgbe_hw * hw ) ;
static s32 ixgbe_init_rx_addrs ( struct ixgbe_hw * hw ) ;
static s32 ixgbe_mta_vector ( struct ixgbe_hw * hw , u8 * mc_addr ) ;
static void ixgbe_add_mc_addr ( struct ixgbe_hw * hw , u8 * mc_addr ) ;
/**
* ixgbe_start_hw - Prepare hardware for TX / RX
* @ 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
* */
s32 ixgbe_start_hw ( struct ixgbe_hw * hw )
{
u32 ctrl_ext ;
/* Set the media type */
hw - > phy . media_type = hw - > mac . ops . get_media_type ( hw ) ;
/* Identify the PHY */
ixgbe_identify_phy ( hw ) ;
/*
* Store MAC address from RAR0 , clear receive address registers , and
* clear the multicast table
*/
ixgbe_init_rx_addrs ( hw ) ;
/* Clear the VLAN filter table */
ixgbe_clear_vfta ( hw ) ;
/* Set up link */
2007-10-31 15:22:10 -07:00
hw - > mac . ops . setup_link ( hw ) ;
2007-09-15 14:07:45 -07:00
/* Clear statistics registers */
ixgbe_clear_hw_cntrs ( hw ) ;
/* 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-10-31 15:22:10 -07:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-15 14:07:45 -07:00
/* Clear adapter stopped flag */
hw - > adapter_stopped = false ;
return 0 ;
}
/**
* ixgbe_init_hw - Generic hardware initialization
* @ hw : pointer to hardware structure
*
* Initialize the hardware by reseting the hardware , 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
* */
s32 ixgbe_init_hw ( struct ixgbe_hw * hw )
{
/* Reset the hardware */
hw - > mac . ops . reset ( hw ) ;
/* Start the HW */
ixgbe_start_hw ( hw ) ;
return 0 ;
}
/**
* ixgbe_clear_hw_cntrs - Generic clear hardware counters
* @ hw : pointer to hardware structure
*
* Clears all hardware statistics counters by reading them from the hardware
* Statistics counters are clear on read .
* */
static s32 ixgbe_clear_hw_cntrs ( struct ixgbe_hw * hw )
{
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 ;
}
/**
* ixgbe_get_mac_addr - Generic get MAC address
* @ 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
* */
s32 ixgbe_get_mac_addr ( struct ixgbe_hw * hw , u8 * mac_addr )
{
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 ;
}
s32 ixgbe_read_part_num ( struct ixgbe_hw * hw , u32 * part_num )
{
s32 ret_val ;
u16 data ;
ret_val = ixgbe_read_eeprom ( hw , IXGBE_PBANUM0_PTR , & data ) ;
if ( ret_val ) {
hw_dbg ( hw , " NVM Read Error \n " ) ;
return ret_val ;
}
* part_num = ( u32 ) ( data < < 16 ) ;
ret_val = ixgbe_read_eeprom ( hw , IXGBE_PBANUM1_PTR , & data ) ;
if ( ret_val ) {
hw_dbg ( hw , " NVM Read Error \n " ) ;
return ret_val ;
}
* part_num | = data ;
return 0 ;
}
/**
* ixgbe_stop_adapter - Generic stop TX / RX units
* @ 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 .
* */
s32 ixgbe_stop_adapter ( struct ixgbe_hw * hw )
{
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 ) ;
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. */
number_of_queues = hw - > mac . num_tx_queues ;
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 ) ;
}
}
return 0 ;
}
/**
* ixgbe_led_on - Turns on the software controllable LEDs .
* @ hw : pointer to hardware structure
* @ index : led number to turn on
* */
s32 ixgbe_led_on ( struct ixgbe_hw * hw , u32 index )
{
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-10-31 15:22:10 -07:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-15 14:07:45 -07:00
return 0 ;
}
/**
* ixgbe_led_off - Turns off the software controllable LEDs .
* @ hw : pointer to hardware structure
* @ index : led number to turn off
* */
s32 ixgbe_led_off ( struct ixgbe_hw * hw , u32 index )
{
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-10-31 15:22:10 -07:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-15 14:07:45 -07:00
return 0 ;
}
/**
* ixgbe_init_eeprom - Initialize EEPROM params
* @ hw : pointer to hardware structure
*
* Initializes the EEPROM parameters ixgbe_eeprom_info within the
* ixgbe_hw struct in order to set up EEPROM access .
* */
s32 ixgbe_init_eeprom ( struct ixgbe_hw * hw )
{
struct ixgbe_eeprom_info * eeprom = & hw - > eeprom ;
u32 eec ;
u16 eeprom_size ;
if ( eeprom - > type = = ixgbe_eeprom_uninitialized ) {
eeprom - > type = ixgbe_eeprom_none ;
/*
* 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 ;
}
/**
* ixgbe_read_eeprom - Read EEPROM word using EERD
* @ 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 .
* */
s32 ixgbe_read_eeprom ( struct ixgbe_hw * hw , u16 offset , u16 * data )
{
u32 eerd ;
s32 status ;
eerd = ( offset < < IXGBE_EEPROM_READ_ADDR_SHIFT ) +
IXGBE_EEPROM_READ_REG_START ;
IXGBE_WRITE_REG ( hw , IXGBE_EERD , eerd ) ;
status = ixgbe_poll_eeprom_eerd_done ( hw ) ;
if ( status = = 0 )
* data = ( IXGBE_READ_REG ( hw , IXGBE_EERD ) > >
IXGBE_EEPROM_READ_REG_DATA ) ;
else
hw_dbg ( hw , " Eeprom read timed out \n " ) ;
return status ;
}
/**
* ixgbe_poll_eeprom_eerd_done - Poll EERD status
* @ hw : pointer to hardware structure
*
* Polls the status bit ( bit 1 ) of the EERD to determine when the read is done .
* */
static s32 ixgbe_poll_eeprom_eerd_done ( struct ixgbe_hw * hw )
{
u32 i ;
u32 reg ;
s32 status = IXGBE_ERR_EEPROM ;
for ( i = 0 ; i < IXGBE_EERD_ATTEMPTS ; i + + ) {
reg = IXGBE_READ_REG ( hw , IXGBE_EERD ) ;
if ( reg & IXGBE_EEPROM_READ_REG_DONE ) {
status = 0 ;
break ;
}
udelay ( 5 ) ;
}
return status ;
}
/**
* 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 "
" not granted. \n " ) ;
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-10-31 15:22:10 -07:00
IXGBE_WRITE_FLUSH ( hw ) ;
2007-09-15 14:07:45 -07: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 + + ) {
if ( ixgbe_read_eeprom ( hw , i , & word ) ! = 0 ) {
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 + + ) {
ixgbe_read_eeprom ( hw , i , & pointer ) ;
/* Make sure the pointer seems valid */
if ( pointer ! = 0xFFFF & & pointer ! = 0 ) {
ixgbe_read_eeprom ( hw , pointer , & length ) ;
if ( length ! = 0xFFFF & & length ! = 0 ) {
for ( j = pointer + 1 ; j < = pointer + length ; j + + ) {
ixgbe_read_eeprom ( hw , j , & word ) ;
checksum + = word ;
}
}
}
}
checksum = ( u16 ) IXGBE_EEPROM_SUM - checksum ;
return checksum ;
}
/**
* ixgbe_validate_eeprom_checksum - Validate EEPROM checksum
* @ 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 .
* */
s32 ixgbe_validate_eeprom_checksum ( struct ixgbe_hw * hw , u16 * checksum_val )
{
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
*/
status = ixgbe_read_eeprom ( hw , 0 , & checksum ) ;
if ( status = = 0 ) {
checksum = ixgbe_calc_eeprom_checksum ( hw ) ;
ixgbe_read_eeprom ( hw , IXGBE_EEPROM_CHECKSUM , & read_checksum ) ;
/*
* 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 ;
}
/**
* 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 & &
mac_addr [ 3 ] = = 0 & & mac_addr [ 4 ] = = 0 & & mac_addr [ 5 ] = = 0 )
status = IXGBE_ERR_INVALID_MAC_ADDR ;
return status ;
}
/**
* ixgbe_set_rar - Set RX address register
* @ hw : pointer to hardware structure
* @ addr : Address to put into receive address register
* @ index : Receive address register to write
* @ vind : Vind to set RAR to
* @ enable_addr : set flag that address is active
*
* Puts an ethernet address into a receive address register .
* */
s32 ixgbe_set_rar ( struct ixgbe_hw * hw , u32 index , u8 * addr , u32 vind ,
u32 enable_addr )
{
u32 rar_low , rar_high ;
/*
* HW expects these in little endian so we reverse the byte order from
* network order ( big endian ) to little endian
*/
rar_low = ( ( u32 ) addr [ 0 ] |
( ( u32 ) addr [ 1 ] < < 8 ) |
( ( u32 ) addr [ 2 ] < < 16 ) |
( ( u32 ) addr [ 3 ] < < 24 ) ) ;
rar_high = ( ( u32 ) addr [ 4 ] |
( ( u32 ) addr [ 5 ] < < 8 ) |
( ( vind < < IXGBE_RAH_VIND_SHIFT ) & IXGBE_RAH_VIND_MASK ) ) ;
if ( enable_addr ! = 0 )
rar_high | = IXGBE_RAH_AV ;
IXGBE_WRITE_REG ( hw , IXGBE_RAL ( index ) , rar_low ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RAH ( index ) , rar_high ) ;
return 0 ;
}
/**
* ixgbe_init_rx_addrs - Initializes receive address filters .
* @ hw : pointer to hardware structure
*
* Places the MAC address in receive address register 0 and clears the rest
* of the receive addresss registers . Clears the multicast table . Assumes
* the receiver is in reset when the routine is called .
* */
static s32 ixgbe_init_rx_addrs ( struct ixgbe_hw * hw )
{
u32 i ;
u32 rar_entries = hw - > mac . num_rx_addrs ;
/*
* 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 */
ixgbe_get_mac_addr ( hw , hw - > mac . addr ) ;
hw_dbg ( hw , " Keeping Current RAR0 Addr =%.2X %.2X %.2X " ,
hw - > mac . addr [ 0 ] , hw - > mac . addr [ 1 ] ,
hw - > mac . addr [ 2 ] ) ;
hw_dbg ( hw , " %.2X %.2X %.2X \n " , hw - > mac . addr [ 3 ] ,
hw - > mac . addr [ 4 ] , hw - > mac . addr [ 5 ] ) ;
} else {
/* Setup the receive address. */
hw_dbg ( hw , " Overriding MAC Address in RAR[0] \n " ) ;
hw_dbg ( hw , " New MAC Addr =%.2X %.2X %.2X " ,
hw - > mac . addr [ 0 ] , hw - > mac . addr [ 1 ] ,
hw - > mac . addr [ 2 ] ) ;
hw_dbg ( hw , " %.2X %.2X %.2X \n " , hw - > mac . addr [ 3 ] ,
hw - > mac . addr [ 4 ] , hw - > mac . addr [ 5 ] ) ;
ixgbe_set_rar ( hw , 0 , hw - > mac . addr , 0 , IXGBE_RAH_AV ) ;
}
hw - > addr_ctrl . rar_used_count = 1 ;
/* Zero out the other receive addresses. */
hw_dbg ( hw , " Clearing RAR[1-15] \n " ) ;
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 " ) ;
for ( i = 0 ; i < IXGBE_MC_TBL_SIZE ; i + + )
IXGBE_WRITE_REG ( hw , IXGBE_MTA ( i ) , 0 ) ;
return 0 ;
}
/**
* 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
* by the MO field of the MCSTCTRL . The MO field is set during initalization
* 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 ) {
case 0 : /* use bits [47:36] of the address */
vector = ( ( mc_addr [ 4 ] > > 4 ) | ( ( ( u16 ) mc_addr [ 5 ] ) < < 4 ) ) ;
break ;
case 1 : /* use bits [46:35] of the address */
vector = ( ( mc_addr [ 4 ] > > 3 ) | ( ( ( u16 ) mc_addr [ 5 ] ) < < 5 ) ) ;
break ;
case 2 : /* use bits [45:34] of the address */
vector = ( ( mc_addr [ 4 ] > > 2 ) | ( ( ( u16 ) mc_addr [ 5 ] ) < < 6 ) ) ;
break ;
case 3 : /* use bits [43:32] of the address */
vector = ( ( mc_addr [ 4 ] ) | ( ( ( u16 ) mc_addr [ 5 ] ) < < 8 ) ) ;
break ;
default : /* Invalid mc_filter_type */
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 ) ;
}
/**
* ixgbe_add_mc_addr - Adds a multicast address .
* @ hw : pointer to hardware structure
* @ mc_addr : new multicast address
*
* Adds it to unused receive address register or to the multicast table .
* */
static void ixgbe_add_mc_addr ( struct ixgbe_hw * hw , u8 * mc_addr )
{
u32 rar_entries = hw - > mac . num_rx_addrs ;
hw_dbg ( hw , " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X \n " ,
mc_addr [ 0 ] , mc_addr [ 1 ] , mc_addr [ 2 ] ,
mc_addr [ 3 ] , mc_addr [ 4 ] , mc_addr [ 5 ] ) ;
/*
* Place this multicast address in the RAR if there is room ,
* else put it in the MTA
*/
if ( hw - > addr_ctrl . rar_used_count < rar_entries ) {
ixgbe_set_rar ( hw , hw - > addr_ctrl . rar_used_count ,
mc_addr , 0 , IXGBE_RAH_AV ) ;
hw_dbg ( hw , " Added a multicast address to RAR[%d] \n " ,
hw - > addr_ctrl . rar_used_count ) ;
hw - > addr_ctrl . rar_used_count + + ;
hw - > addr_ctrl . mc_addr_in_rar_count + + ;
} else {
ixgbe_set_mta ( hw , mc_addr ) ;
}
hw_dbg ( hw , " ixgbe_add_mc_addr Complete \n " ) ;
}
/**
* ixgbe_update_mc_addr_list - Updates MAC list of multicast addresses
* @ hw : pointer to hardware structure
* @ mc_addr_list : the list of new multicast addresses
* @ mc_addr_count : number of addresses
* @ pad : number of bytes between addresses in the list
*
* The given list replaces any existing list . Clears the MC addrs from receive
* address registers and the multicast table . Uses unsed receive address
* registers for the first multicast addresses , and hashes the rest into the
* multicast table .
* */
s32 ixgbe_update_mc_addr_list ( struct ixgbe_hw * hw , u8 * mc_addr_list ,
u32 mc_addr_count , u32 pad )
{
u32 i ;
u32 rar_entries = hw - > mac . num_rx_addrs ;
/*
* Set the new number of MC addresses that we are being requested to
* use .
*/
hw - > addr_ctrl . num_mc_addrs = mc_addr_count ;
hw - > addr_ctrl . rar_used_count - = hw - > addr_ctrl . mc_addr_in_rar_count ;
hw - > addr_ctrl . mc_addr_in_rar_count = 0 ;
hw - > addr_ctrl . mta_in_use = 0 ;
/* Zero out the other receive addresses. */
hw_dbg ( hw , " Clearing RAR[1-15] \n " ) ;
for ( i = hw - > addr_ctrl . rar_used_count ; i < rar_entries ; i + + ) {
IXGBE_WRITE_REG ( hw , IXGBE_RAL ( i ) , 0 ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RAH ( i ) , 0 ) ;
}
/* Clear the MTA */
hw_dbg ( hw , " Clearing MTA \n " ) ;
for ( i = 0 ; i < IXGBE_MC_TBL_SIZE ; i + + )
IXGBE_WRITE_REG ( hw , IXGBE_MTA ( i ) , 0 ) ;
/* Add the new addresses */
for ( i = 0 ; i < mc_addr_count ; i + + ) {
hw_dbg ( hw , " Adding the multicast addresses: \n " ) ;
ixgbe_add_mc_addr ( hw , mc_addr_list +
( i * ( IXGBE_ETH_LENGTH_OF_ADDRESS + pad ) ) ) ;
}
/* Enable mta */
if ( hw - > addr_ctrl . mta_in_use > 0 )
IXGBE_WRITE_REG ( hw , IXGBE_MCSTCTRL ,
IXGBE_MCSTCTRL_MFE | hw - > mac . mc_filter_type ) ;
hw_dbg ( hw , " ixgbe_update_mc_addr_list Complete \n " ) ;
return 0 ;
}
/**
* ixgbe_clear_vfta - Clear VLAN filter table
* @ hw : pointer to hardware structure
*
* Clears the VLAN filer table , and the VMDq index associated with the filter
* */
static s32 ixgbe_clear_vfta ( struct ixgbe_hw * hw )
{
u32 offset ;
u32 vlanbyte ;
for ( offset = 0 ; offset < IXGBE_VLAN_FILTER_TBL_SIZE ; offset + + )
IXGBE_WRITE_REG ( hw , IXGBE_VFTA ( offset ) , 0 ) ;
for ( vlanbyte = 0 ; vlanbyte < 4 ; vlanbyte + + )
for ( offset = 0 ; offset < IXGBE_VLAN_FILTER_TBL_SIZE ; offset + + )
IXGBE_WRITE_REG ( hw , IXGBE_VFTAVIND ( vlanbyte , offset ) ,
0 ) ;
return 0 ;
}
/**
* ixgbe_set_vfta - 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 VFTA
* @ vlan_on : boolean flag to turn on / off VLAN in VFTA
*
* Turn on / off specified VLAN in the VLAN filter table .
* */
s32 ixgbe_set_vfta ( struct ixgbe_hw * hw , u32 vlan , u32 vind ,
bool vlan_on )
{
u32 VftaIndex ;
u32 BitOffset ;
u32 VftaReg ;
u32 VftaByte ;
/* Determine 32-bit word position in array */
VftaIndex = ( vlan > > 5 ) & 0x7F ; /* upper seven bits */
/* Determine the location of the (VMD) queue index */
VftaByte = ( ( vlan > > 3 ) & 0x03 ) ; /* bits (4:3) indicating byte array */
BitOffset = ( vlan & 0x7 ) < < 2 ; /* lower 3 bits indicate nibble */
/* Set the nibble for VMD queue index */
VftaReg = IXGBE_READ_REG ( hw , IXGBE_VFTAVIND ( VftaByte , VftaIndex ) ) ;
VftaReg & = ( ~ ( 0x0F < < BitOffset ) ) ;
VftaReg | = ( vind < < BitOffset ) ;
IXGBE_WRITE_REG ( hw , IXGBE_VFTAVIND ( VftaByte , VftaIndex ) , VftaReg ) ;
/* Determine the location of the bit for this VLAN id */
BitOffset = vlan & 0x1F ; /* lower five bits */
VftaReg = IXGBE_READ_REG ( hw , IXGBE_VFTA ( VftaIndex ) ) ;
if ( vlan_on )
/* Turn on this VLAN id */
VftaReg | = ( 1 < < BitOffset ) ;
else
/* Turn off this VLAN id */
VftaReg & = ~ ( 1 < < BitOffset ) ;
IXGBE_WRITE_REG ( hw , IXGBE_VFTA ( VftaIndex ) , VftaReg ) ;
return 0 ;
}
/**
* ixgbe_setup_fc - Configure flow control settings
* @ hw : pointer to hardware structure
* @ packetbuf_num : packet buffer number ( 0 - 7 )
*
* Configures the flow control settings based on SW configuration .
* This function is used for 802.3 x flow control configuration only .
* */
s32 ixgbe_setup_fc ( struct ixgbe_hw * hw , s32 packetbuf_num )
{
u32 frctl_reg ;
u32 rmcs_reg ;
if ( packetbuf_num < 0 | | packetbuf_num > 7 )
2007-11-19 17:48:23 -08:00
hw_dbg ( hw , " Invalid packet buffer number [%d], expected range "
2007-09-15 14:07:45 -07:00
" is 0-7 \n " , packetbuf_num ) ;
frctl_reg = IXGBE_READ_REG ( hw , IXGBE_FCTRL ) ;
frctl_reg & = ~ ( IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE ) ;
rmcs_reg = IXGBE_READ_REG ( hw , IXGBE_RMCS ) ;
rmcs_reg & = ~ ( IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X ) ;
/*
* We want to save off the original Flow Control configuration just in
* case we get disconnected and then reconnected into a different hub
* or switch with different Flow Control capabilities .
*/
hw - > fc . type = hw - > fc . original_type ;
/*
* The possible values of the " flow_control " parameter 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 . type ) {
case ixgbe_fc_none :
break ;
case ixgbe_fc_rx_pause :
/*
* RX Flow control is enabled ,
* and TX Flow control is disabled .
*/
frctl_reg | = IXGBE_FCTRL_RFCE ;
break ;
case ixgbe_fc_tx_pause :
/*
* TX Flow control is enabled , and RX Flow control is disabled ,
* by a software over - ride .
*/
rmcs_reg | = IXGBE_RMCS_TFCE_802_3X ;
break ;
case ixgbe_fc_full :
/*
* Flow control ( both RX and TX ) is enabled by a software
* over - ride .
*/
frctl_reg | = IXGBE_FCTRL_RFCE ;
rmcs_reg | = IXGBE_RMCS_TFCE_802_3X ;
break ;
default :
/* We should never get here. The value should be 0-3. */
hw_dbg ( hw , " Flow control param set incorrectly \n " ) ;
break ;
}
/* Enable 802.3x based flow control settings. */
IXGBE_WRITE_REG ( hw , IXGBE_FCTRL , frctl_reg ) ;
IXGBE_WRITE_REG ( hw , IXGBE_RMCS , rmcs_reg ) ;
/*
* We need to set up the Receive Threshold high and low water
* marks as well as ( optionally ) enabling the transmission of
* XON frames .
*/
if ( hw - > fc . type & ixgbe_fc_tx_pause ) {
if ( hw - > fc . send_xon ) {
IXGBE_WRITE_REG ( hw , IXGBE_FCRTL ( packetbuf_num ) ,
( hw - > fc . low_water | IXGBE_FCRTL_XONE ) ) ;
} else {
IXGBE_WRITE_REG ( hw , IXGBE_FCRTL ( packetbuf_num ) ,
hw - > fc . low_water ) ;
}
IXGBE_WRITE_REG ( hw , IXGBE_FCRTH ( packetbuf_num ) ,
( hw - > fc . high_water ) | IXGBE_FCRTH_FCEN ) ;
}
IXGBE_WRITE_REG ( hw , IXGBE_FCTTV ( 0 ) , hw - > fc . pause_time ) ;
IXGBE_WRITE_REG ( hw , IXGBE_FCRTV , ( hw - > fc . pause_time > > 1 ) ) ;
return 0 ;
}
/**
* 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 )
{
u32 ctrl ;
s32 i ;
s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING ;
ctrl = IXGBE_READ_REG ( hw , IXGBE_CTRL ) ;
ctrl | = IXGBE_CTRL_GIO_DIS ;
IXGBE_WRITE_REG ( hw , IXGBE_CTRL , ctrl ) ;
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 ;
}
/**
* ixgbe_acquire_swfw_sync - Aquire SWFW semaphore
* @ hw : pointer to hardware structure
* @ mask : Mask to specify wich semaphore to acquire
*
* Aquires the SWFW semaphore throught the GSSR register for the specified
* 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 ) )
return - IXGBE_ERR_SWFW_SYNC ;
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 " ) ;
return - IXGBE_ERR_SWFW_SYNC ;
}
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
* @ mask : Mask to specify wich semaphore to release
*
* Releases the SWFW semaphore throught the GSSR register for the specified
* 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 ) ;
}
/**
2007-10-31 15:22:10 -07:00
* ixgbe_read_analog_reg8 - Reads 8 bit Atlas analog register
2007-09-15 14:07:45 -07:00
* @ hw : pointer to hardware structure
* @ reg : analog register to read
* @ val : read value
*
* Performs write operation to analog register specified .
* */
s32 ixgbe_read_analog_reg8 ( struct ixgbe_hw * hw , u32 reg , u8 * val )
{
u32 atlas_ctl ;
IXGBE_WRITE_REG ( hw , IXGBE_ATLASCTL ,
IXGBE_ATLASCTL_WRITE_CMD | ( reg < < 8 ) ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 10 ) ;
atlas_ctl = IXGBE_READ_REG ( hw , IXGBE_ATLASCTL ) ;
* val = ( u8 ) atlas_ctl ;
return 0 ;
}
/**
2007-10-31 15:22:10 -07:00
* ixgbe_write_analog_reg8 - Writes 8 bit Atlas analog register
2007-09-15 14:07:45 -07:00
* @ hw : pointer to hardware structure
* @ reg : atlas register to write
* @ val : value to write
*
* Performs write operation to Atlas analog register specified .
* */
s32 ixgbe_write_analog_reg8 ( struct ixgbe_hw * hw , u32 reg , u8 val )
{
u32 atlas_ctl ;
atlas_ctl = ( reg < < 8 ) | val ;
IXGBE_WRITE_REG ( hw , IXGBE_ATLASCTL , atlas_ctl ) ;
IXGBE_WRITE_FLUSH ( hw ) ;
udelay ( 10 ) ;
return 0 ;
}