2008-04-27 12:55:59 +01:00
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2005 - 2006 Fen Systems Ltd .
* Copyright 2006 - 2008 Solarflare Communications Inc .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation , incorporated herein by reference .
*/
# include <linux/bitops.h>
# include <linux/delay.h>
# include <linux/pci.h>
# include <linux/module.h>
# include <linux/seq_file.h>
2008-05-30 22:27:04 +01:00
# include <linux/i2c.h>
2008-12-12 21:43:33 -08:00
# include <linux/mii.h>
2008-04-27 12:55:59 +01:00
# include "net_driver.h"
# include "bitfield.h"
# include "efx.h"
# include "mac.h"
# include "spi.h"
2009-11-29 15:12:08 +00:00
# include "nic.h"
2009-10-23 08:30:36 +00:00
# include "regs.h"
2009-10-23 08:30:46 +00:00
# include "io.h"
2008-04-27 12:55:59 +01:00
# include "mdio_10g.h"
# include "phy.h"
# include "workarounds.h"
2009-11-25 16:09:04 +00:00
/* Hardware control for SFC4000 (aka Falcon). */
2008-04-27 12:55:59 +01:00
2008-12-12 21:34:25 -08:00
static const unsigned int
/* "Large" EEPROM device: Atmel AT25640 or similar
* 8 KB , 16 - bit address , 32 B write block */
large_eeprom_type = ( ( 13 < < SPI_DEV_TYPE_SIZE_LBN )
| ( 2 < < SPI_DEV_TYPE_ADDR_LEN_LBN )
| ( 5 < < SPI_DEV_TYPE_BLOCK_SIZE_LBN ) ) ,
/* Default flash device: Atmel AT25F1024
* 128 KB , 24 - bit address , 32 KB erase block , 256 B write block */
default_flash_type = ( ( 17 < < SPI_DEV_TYPE_SIZE_LBN )
| ( 3 < < SPI_DEV_TYPE_ADDR_LEN_LBN )
| ( 0x52 < < SPI_DEV_TYPE_ERASE_CMD_LBN )
| ( 15 < < SPI_DEV_TYPE_ERASE_SIZE_LBN )
| ( 8 < < SPI_DEV_TYPE_BLOCK_SIZE_LBN ) ) ;
2008-04-27 12:55:59 +01:00
/**************************************************************************
*
* I2C bus - this is a bit - bashing interface using GPIO pins
* Note that it uses the output enables to tristate the outputs
* SDA is the data pin and SCL is the clock
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2008-05-30 22:27:04 +01:00
static void falcon_setsda ( void * data , int state )
2008-04-27 12:55:59 +01:00
{
2008-05-30 22:27:04 +01:00
struct efx_nic * efx = ( struct efx_nic * ) data ;
2008-04-27 12:55:59 +01:00
efx_oword_t reg ;
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_GPIO_CTL ) ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( reg , FRF_AB_GPIO3_OEN , ! state ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_GPIO_CTL ) ;
2008-04-27 12:55:59 +01:00
}
2008-05-30 22:27:04 +01:00
static void falcon_setscl ( void * data , int state )
2008-04-27 12:55:59 +01:00
{
2008-05-30 22:27:04 +01:00
struct efx_nic * efx = ( struct efx_nic * ) data ;
2008-04-27 12:55:59 +01:00
efx_oword_t reg ;
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_GPIO_CTL ) ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( reg , FRF_AB_GPIO0_OEN , ! state ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_GPIO_CTL ) ;
2008-05-30 22:27:04 +01:00
}
2009-11-29 15:14:45 +00:00
static int falcon_getsda ( void * data )
{
struct efx_nic * efx = ( struct efx_nic * ) data ;
efx_oword_t reg ;
2008-04-27 12:55:59 +01:00
2009-11-29 15:14:45 +00:00
efx_reado ( efx , & reg , FR_AB_GPIO_CTL ) ;
return EFX_OWORD_FIELD ( reg , FRF_AB_GPIO3_IN ) ;
}
2008-04-27 12:55:59 +01:00
2009-11-29 15:14:45 +00:00
static int falcon_getscl ( void * data )
{
struct efx_nic * efx = ( struct efx_nic * ) data ;
efx_oword_t reg ;
2008-04-27 12:55:59 +01:00
2009-11-29 15:14:45 +00:00
efx_reado ( efx , & reg , FR_AB_GPIO_CTL ) ;
return EFX_OWORD_FIELD ( reg , FRF_AB_GPIO0_IN ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-29 15:14:45 +00:00
static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
. setsda = falcon_setsda ,
. setscl = falcon_setscl ,
. getsda = falcon_getsda ,
. getscl = falcon_getscl ,
. udelay = 5 ,
/* Wait up to 50 ms for slave to let us pull SCL high */
. timeout = DIV_ROUND_UP ( HZ , 20 ) ,
} ;
2009-11-29 03:42:31 +00:00
static void falcon_push_irq_moderation ( struct efx_channel * channel )
2008-04-27 12:55:59 +01:00
{
efx_dword_t timer_cmd ;
struct efx_nic * efx = channel - > efx ;
/* Set timer register */
if ( channel - > irq_moderation ) {
EFX_POPULATE_DWORD_2 ( timer_cmd ,
2009-10-23 08:30:36 +00:00
FRF_AB_TC_TIMER_MODE ,
FFE_BB_TIMER_MODE_INT_HLDOFF ,
FRF_AB_TC_TIMER_VAL ,
2009-10-23 08:32:13 +00:00
channel - > irq_moderation - 1 ) ;
2008-04-27 12:55:59 +01:00
} else {
EFX_POPULATE_DWORD_2 ( timer_cmd ,
2009-10-23 08:30:36 +00:00
FRF_AB_TC_TIMER_MODE ,
FFE_BB_TIMER_MODE_DIS ,
FRF_AB_TC_TIMER_VAL , 0 ) ;
2008-04-27 12:55:59 +01:00
}
2009-10-23 08:30:36 +00:00
BUILD_BUG_ON ( FR_AA_TIMER_COMMAND_KER ! = FR_BZ_TIMER_COMMAND_P0 ) ;
2009-10-23 08:30:46 +00:00
efx_writed_page_locked ( efx , & timer_cmd , FR_BZ_TIMER_COMMAND_P0 ,
channel - > channel ) ;
2009-11-25 16:09:55 +00:00
}
2009-11-29 03:42:41 +00:00
static void falcon_deconfigure_mac_wrapper ( struct efx_nic * efx ) ;
2009-11-25 16:09:55 +00:00
static void falcon_prepare_flush ( struct efx_nic * efx )
{
falcon_deconfigure_mac_wrapper ( efx ) ;
/* Wait for the tx and rx fifo's to get to the next packet boundary
* ( ~ 1 ms without back - pressure ) , then to drain the remainder of the
* fifo ' s at data path speeds ( negligible ) , with a healthy margin . */
msleep ( 10 ) ;
2008-09-01 12:49:37 +01:00
}
2008-04-27 12:55:59 +01:00
/* Acknowledge a legacy interrupt from Falcon
*
* This acknowledges a legacy ( not MSI ) interrupt via INT_ACK_KER_REG .
*
* Due to SFC bug 3706 ( silicon revision < = A1 ) reads can be duplicated in the
* BIU . Interrupt acknowledge is read sensitive so must write instead
* ( then read to ensure the BIU collector is flushed )
*
* NB most hardware supports MSI interrupts
*/
2009-11-29 03:43:56 +00:00
inline void falcon_irq_ack_a1 ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
efx_dword_t reg ;
2009-10-23 08:30:36 +00:00
EFX_POPULATE_DWORD_1 ( reg , FRF_AA_INT_ACK_KER_FIELD , 0xb7eb7e ) ;
2009-10-23 08:30:46 +00:00
efx_writed ( efx , & reg , FR_AA_INT_ACK_KER ) ;
efx_readd ( efx , & reg , FR_AA_WORK_AROUND_BROKEN_PCI_READS ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-29 03:43:56 +00:00
irqreturn_t falcon_legacy_interrupt_a1 ( int irq , void * dev_id )
2008-04-27 12:55:59 +01:00
{
2008-05-16 21:20:00 +01:00
struct efx_nic * efx = dev_id ;
efx_oword_t * int_ker = efx - > irq_status . addr ;
2008-04-27 12:55:59 +01:00
struct efx_channel * channel ;
int syserr ;
int queues ;
/* Check to see if this is our interrupt. If it isn't, we
* exit without having touched the hardware .
*/
if ( unlikely ( EFX_OWORD_IS_ZERO ( * int_ker ) ) ) {
EFX_TRACE ( efx , " IRQ %d on CPU %d not for me \n " , irq ,
raw_smp_processor_id ( ) ) ;
return IRQ_NONE ;
}
efx - > last_irq_cpu = raw_smp_processor_id ( ) ;
EFX_TRACE ( efx , " IRQ %d on CPU %d status " EFX_OWORD_FMT " \n " ,
irq , raw_smp_processor_id ( ) , EFX_OWORD_VAL ( * int_ker ) ) ;
/* Check to see if we have a serious error condition */
2009-10-23 08:30:36 +00:00
syserr = EFX_OWORD_FIELD ( * int_ker , FSF_AZ_NET_IVEC_FATAL_INT ) ;
2008-04-27 12:55:59 +01:00
if ( unlikely ( syserr ) )
2009-11-29 03:43:56 +00:00
return efx_nic_fatal_interrupt ( efx ) ;
2008-04-27 12:55:59 +01:00
/* Determine interrupting queues, clear interrupt status
* register and acknowledge the device interrupt .
*/
2009-11-29 03:42:10 +00:00
BUILD_BUG_ON ( FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS ) ;
queues = EFX_OWORD_FIELD ( * int_ker , FSF_AZ_NET_IVEC_INT_Q ) ;
2008-04-27 12:55:59 +01:00
EFX_ZERO_OWORD ( * int_ker ) ;
wmb ( ) ; /* Ensure the vector is cleared before interrupt ack */
falcon_irq_ack_a1 ( efx ) ;
/* Schedule processing of any interrupting queues */
channel = & efx - > channel [ 0 ] ;
while ( queues ) {
if ( queues & 0x01 )
efx_schedule_channel ( channel ) ;
channel + + ;
queues > > = 1 ;
}
return IRQ_HANDLED ;
}
/**************************************************************************
*
* EEPROM / flash
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2008-12-12 21:56:11 -08:00
# define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
2008-04-27 12:55:59 +01:00
2008-12-12 21:33:50 -08:00
static int falcon_spi_poll ( struct efx_nic * efx )
{
efx_oword_t reg ;
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_EE_SPI_HCMD ) ;
2009-10-23 08:30:36 +00:00
return EFX_OWORD_FIELD ( reg , FRF_AB_EE_SPI_HCMD_CMD_EN ) ? - EBUSY : 0 ;
2008-12-12 21:33:50 -08:00
}
2008-04-27 12:55:59 +01:00
/* Wait for SPI command completion */
static int falcon_spi_wait ( struct efx_nic * efx )
{
2008-12-12 21:33:50 -08:00
/* Most commands will finish quickly, so we start polling at
* very short intervals . Sometimes the command may have to
* wait for VPD or expansion ROM access outside of our
* control , so we allow up to 100 ms . */
unsigned long timeout = jiffies + 1 + DIV_ROUND_UP ( HZ , 10 ) ;
int i ;
for ( i = 0 ; i < 10 ; i + + ) {
if ( ! falcon_spi_poll ( efx ) )
return 0 ;
udelay ( 10 ) ;
}
2008-04-27 12:55:59 +01:00
2008-09-01 12:47:16 +01:00
for ( ; ; ) {
2008-12-12 21:33:50 -08:00
if ( ! falcon_spi_poll ( efx ) )
2008-04-27 12:55:59 +01:00
return 0 ;
2008-09-01 12:47:16 +01:00
if ( time_after_eq ( jiffies , timeout ) ) {
EFX_ERR ( efx , " timed out waiting for SPI \n " ) ;
return - ETIMEDOUT ;
}
2008-12-12 21:33:50 -08:00
schedule_timeout_uninterruptible ( 1 ) ;
2008-09-01 12:47:16 +01:00
}
2008-04-27 12:55:59 +01:00
}
2009-11-29 15:10:44 +00:00
int falcon_spi_cmd ( struct efx_nic * efx , const struct efx_spi_device * spi ,
2008-11-04 20:34:28 +00:00
unsigned int command , int address ,
2008-12-12 21:56:11 -08:00
const void * in , void * out , size_t len )
2008-04-27 12:55:59 +01:00
{
2008-09-01 12:47:16 +01:00
bool addressed = ( address > = 0 ) ;
bool reading = ( out ! = NULL ) ;
2008-04-27 12:55:59 +01:00
efx_oword_t reg ;
int rc ;
2008-09-01 12:47:16 +01:00
/* Input validation */
if ( len > FALCON_SPI_MAX_LEN )
return - EINVAL ;
2008-11-04 20:34:28 +00:00
BUG_ON ( ! mutex_is_locked ( & efx - > spi_lock ) ) ;
2008-04-27 12:55:59 +01:00
2008-12-12 21:33:50 -08:00
/* Check that previous command is not still running */
rc = falcon_spi_poll ( efx ) ;
2008-04-27 12:55:59 +01:00
if ( rc )
return rc ;
2008-09-01 12:47:16 +01:00
/* Program address register, if we have an address */
if ( addressed ) {
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_1 ( reg , FRF_AB_EE_SPI_HADR_ADR , address ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_EE_SPI_HADR ) ;
2008-09-01 12:47:16 +01:00
}
/* Program data register, if we have data */
if ( in ! = NULL ) {
memcpy ( & reg , in , len ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_EE_SPI_HDATA ) ;
2008-09-01 12:47:16 +01:00
}
2008-04-27 12:55:59 +01:00
2008-09-01 12:47:16 +01:00
/* Issue read/write command */
2008-04-27 12:55:59 +01:00
EFX_POPULATE_OWORD_7 ( reg ,
2009-10-23 08:30:36 +00:00
FRF_AB_EE_SPI_HCMD_CMD_EN , 1 ,
FRF_AB_EE_SPI_HCMD_SF_SEL , spi - > device_id ,
FRF_AB_EE_SPI_HCMD_DABCNT , len ,
FRF_AB_EE_SPI_HCMD_READ , reading ,
FRF_AB_EE_SPI_HCMD_DUBCNT , 0 ,
FRF_AB_EE_SPI_HCMD_ADBCNT ,
2008-09-01 12:47:16 +01:00
( addressed ? spi - > addr_len : 0 ) ,
2009-10-23 08:30:36 +00:00
FRF_AB_EE_SPI_HCMD_ENC , command ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_EE_SPI_HCMD ) ;
2008-04-27 12:55:59 +01:00
2008-09-01 12:47:16 +01:00
/* Wait for read/write to complete */
2008-04-27 12:55:59 +01:00
rc = falcon_spi_wait ( efx ) ;
if ( rc )
return rc ;
/* Read data */
2008-09-01 12:47:16 +01:00
if ( out ! = NULL ) {
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_EE_SPI_HDATA ) ;
2008-09-01 12:47:16 +01:00
memcpy ( out , & reg , len ) ;
}
2008-04-27 12:55:59 +01:00
return 0 ;
}
2008-12-12 21:56:11 -08:00
static size_t
falcon_spi_write_limit ( const struct efx_spi_device * spi , size_t start )
2008-09-01 12:47:16 +01:00
{
return min ( FALCON_SPI_MAX_LEN ,
( spi - > block_size - ( start & ( spi - > block_size - 1 ) ) ) ) ;
}
static inline u8
efx_spi_munge_command ( const struct efx_spi_device * spi ,
const u8 command , const unsigned int address )
{
return command | ( ( ( address > > 8 ) & spi - > munge_address ) < < 3 ) ;
}
2008-12-12 21:33:50 -08:00
/* Wait up to 10 ms for buffered write completion */
2009-11-29 15:10:44 +00:00
int
falcon_spi_wait_write ( struct efx_nic * efx , const struct efx_spi_device * spi )
2008-09-01 12:47:16 +01:00
{
2008-12-12 21:33:50 -08:00
unsigned long timeout = jiffies + 1 + DIV_ROUND_UP ( HZ , 100 ) ;
2008-09-01 12:47:16 +01:00
u8 status ;
2008-12-12 21:33:50 -08:00
int rc ;
2008-09-01 12:47:16 +01:00
2008-12-12 21:33:50 -08:00
for ( ; ; ) {
2009-11-29 15:10:44 +00:00
rc = falcon_spi_cmd ( efx , spi , SPI_RDSR , - 1 , NULL ,
2008-09-01 12:47:16 +01:00
& status , sizeof ( status ) ) ;
if ( rc )
return rc ;
if ( ! ( status & SPI_STATUS_NRDY ) )
return 0 ;
2008-12-12 21:33:50 -08:00
if ( time_after_eq ( jiffies , timeout ) ) {
EFX_ERR ( efx , " SPI write timeout on device %d "
" last status=0x%02x \n " ,
spi - > device_id , status ) ;
return - ETIMEDOUT ;
}
schedule_timeout_uninterruptible ( 1 ) ;
2008-09-01 12:47:16 +01:00
}
}
2009-11-29 15:10:44 +00:00
int falcon_spi_read ( struct efx_nic * efx , const struct efx_spi_device * spi ,
loff_t start , size_t len , size_t * retlen , u8 * buffer )
2008-09-01 12:47:16 +01:00
{
2008-12-12 21:56:11 -08:00
size_t block_len , pos = 0 ;
unsigned int command ;
2008-09-01 12:47:16 +01:00
int rc = 0 ;
while ( pos < len ) {
2008-12-12 21:56:11 -08:00
block_len = min ( len - pos , FALCON_SPI_MAX_LEN ) ;
2008-09-01 12:47:16 +01:00
command = efx_spi_munge_command ( spi , SPI_READ , start + pos ) ;
2009-11-29 15:10:44 +00:00
rc = falcon_spi_cmd ( efx , spi , command , start + pos , NULL ,
2008-09-01 12:47:16 +01:00
buffer + pos , block_len ) ;
if ( rc )
break ;
pos + = block_len ;
/* Avoid locking up the system */
cond_resched ( ) ;
if ( signal_pending ( current ) ) {
rc = - EINTR ;
break ;
}
}
if ( retlen )
* retlen = pos ;
return rc ;
}
2009-11-29 15:10:44 +00:00
int
falcon_spi_write ( struct efx_nic * efx , const struct efx_spi_device * spi ,
loff_t start , size_t len , size_t * retlen , const u8 * buffer )
2008-09-01 12:47:16 +01:00
{
u8 verify_buffer [ FALCON_SPI_MAX_LEN ] ;
2008-12-12 21:56:11 -08:00
size_t block_len , pos = 0 ;
unsigned int command ;
2008-09-01 12:47:16 +01:00
int rc = 0 ;
while ( pos < len ) {
2009-11-29 15:10:44 +00:00
rc = falcon_spi_cmd ( efx , spi , SPI_WREN , - 1 , NULL , NULL , 0 ) ;
2008-09-01 12:47:16 +01:00
if ( rc )
break ;
2008-12-12 21:56:11 -08:00
block_len = min ( len - pos ,
2008-09-01 12:47:16 +01:00
falcon_spi_write_limit ( spi , start + pos ) ) ;
command = efx_spi_munge_command ( spi , SPI_WRITE , start + pos ) ;
2009-11-29 15:10:44 +00:00
rc = falcon_spi_cmd ( efx , spi , command , start + pos ,
2008-09-01 12:47:16 +01:00
buffer + pos , NULL , block_len ) ;
if ( rc )
break ;
2009-11-29 15:10:44 +00:00
rc = falcon_spi_wait_write ( efx , spi ) ;
2008-09-01 12:47:16 +01:00
if ( rc )
break ;
command = efx_spi_munge_command ( spi , SPI_READ , start + pos ) ;
2009-11-29 15:10:44 +00:00
rc = falcon_spi_cmd ( efx , spi , command , start + pos ,
2008-09-01 12:47:16 +01:00
NULL , verify_buffer , block_len ) ;
if ( memcmp ( verify_buffer , buffer + pos , block_len ) ) {
rc = - EIO ;
break ;
}
pos + = block_len ;
/* Avoid locking up the system */
cond_resched ( ) ;
if ( signal_pending ( current ) ) {
rc = - EINTR ;
break ;
}
}
if ( retlen )
* retlen = pos ;
return rc ;
}
2008-04-27 12:55:59 +01:00
/**************************************************************************
*
* MAC wrapper
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2008-12-12 21:50:08 -08:00
2009-11-29 03:42:31 +00:00
static void falcon_push_multicast_hash ( struct efx_nic * efx )
{
union efx_multicast_hash * mc_hash = & efx - > multicast_hash ;
WARN_ON ( ! mutex_is_locked ( & efx - > mac_lock ) ) ;
efx_writeo ( efx , & mc_hash - > oword [ 0 ] , FR_AB_MAC_MC_HASH_REG0 ) ;
efx_writeo ( efx , & mc_hash - > oword [ 1 ] , FR_AB_MAC_MC_HASH_REG1 ) ;
}
2009-11-29 03:42:41 +00:00
static void falcon_reset_macs ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
2009-11-29 03:42:41 +00:00
struct falcon_nic_data * nic_data = efx - > nic_data ;
efx_oword_t reg , mac_ctrl ;
2008-04-27 12:55:59 +01:00
int count ;
2009-11-28 05:36:04 +00:00
if ( efx_nic_rev ( efx ) < EFX_REV_FALCON_B0 ) {
2008-12-12 21:50:08 -08:00
/* It's not safe to use GLB_CTL_REG to reset the
* macs , so instead use the internal MAC resets
*/
if ( ! EFX_IS10G ( efx ) ) {
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_1 ( reg , FRF_AB_GM_SW_RST , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_GM_CFG1 ) ;
2008-12-12 21:50:08 -08:00
udelay ( 1000 ) ;
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_1 ( reg , FRF_AB_GM_SW_RST , 0 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_GM_CFG1 ) ;
2008-12-12 21:50:08 -08:00
udelay ( 1000 ) ;
2009-11-29 03:42:41 +00:00
return ;
2008-12-12 21:50:08 -08:00
} else {
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_1 ( reg , FRF_AB_XM_CORE_RST , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_XM_GLB_CFG ) ;
2008-12-12 21:50:08 -08:00
for ( count = 0 ; count < 10000 ; count + + ) {
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_XM_GLB_CFG ) ;
2009-10-23 08:30:36 +00:00
if ( EFX_OWORD_FIELD ( reg , FRF_AB_XM_CORE_RST ) = =
0 )
2009-11-29 03:42:41 +00:00
return ;
2008-12-12 21:50:08 -08:00
udelay ( 10 ) ;
}
2008-04-27 12:55:59 +01:00
2008-12-12 21:50:08 -08:00
EFX_ERR ( efx , " timed out waiting for XMAC core reset \n " ) ;
}
}
2008-04-27 12:55:59 +01:00
2009-11-29 03:42:41 +00:00
/* Mac stats will fail whist the TX fifo is draining */
WARN_ON ( nic_data - > stats_disable_count = = 0 ) ;
2008-04-27 12:55:59 +01:00
2009-11-29 03:42:41 +00:00
efx_reado ( efx , & mac_ctrl , FR_AB_MAC_CTRL ) ;
EFX_SET_OWORD_FIELD ( mac_ctrl , FRF_BB_TXFIFO_DRAIN_EN , 1 ) ;
efx_writeo ( efx , & mac_ctrl , FR_AB_MAC_CTRL ) ;
2008-04-27 12:55:59 +01:00
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_GLB_CTL ) ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( reg , FRF_AB_RST_XGTX , 1 ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_AB_RST_XGRX , 1 ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_AB_RST_EM , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_GLB_CTL ) ;
2008-04-27 12:55:59 +01:00
count = 0 ;
while ( 1 ) {
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_GLB_CTL ) ;
2009-10-23 08:30:36 +00:00
if ( ! EFX_OWORD_FIELD ( reg , FRF_AB_RST_XGTX ) & &
! EFX_OWORD_FIELD ( reg , FRF_AB_RST_XGRX ) & &
! EFX_OWORD_FIELD ( reg , FRF_AB_RST_EM ) ) {
2008-04-27 12:55:59 +01:00
EFX_LOG ( efx , " Completed MAC reset after %d loops \n " ,
count ) ;
break ;
}
if ( count > 20 ) {
EFX_ERR ( efx , " MAC reset failed \n " ) ;
break ;
}
count + + ;
udelay ( 10 ) ;
}
2009-11-29 03:42:41 +00:00
/* Ensure the correct MAC is selected before statistics
* are re - enabled by the caller */
efx_writeo ( efx , & mac_ctrl , FR_AB_MAC_CTRL ) ;
2008-12-12 21:50:08 -08:00
}
void falcon_drain_tx_fifo ( struct efx_nic * efx )
{
efx_oword_t reg ;
2009-11-28 05:36:04 +00:00
if ( ( efx_nic_rev ( efx ) < EFX_REV_FALCON_B0 ) | |
2008-12-12 21:50:08 -08:00
( efx - > loopback_mode ! = LOOPBACK_NONE ) )
return ;
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_MAC_CTRL ) ;
2008-12-12 21:50:08 -08:00
/* There is no point in draining more than once */
2009-10-23 08:30:36 +00:00
if ( EFX_OWORD_FIELD ( reg , FRF_BB_TXFIFO_DRAIN_EN ) )
2008-12-12 21:50:08 -08:00
return ;
falcon_reset_macs ( efx ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-29 03:42:41 +00:00
static void falcon_deconfigure_mac_wrapper ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
2008-12-12 21:50:08 -08:00
efx_oword_t reg ;
2008-04-27 12:55:59 +01:00
2009-11-28 05:36:04 +00:00
if ( efx_nic_rev ( efx ) < EFX_REV_FALCON_B0 )
2008-04-27 12:55:59 +01:00
return ;
/* Isolate the MAC -> RX */
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AZ_RX_CFG ) ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_INGR_EN , 0 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AZ_RX_CFG ) ;
2008-04-27 12:55:59 +01:00
2009-11-29 03:42:41 +00:00
/* Isolate TX -> MAC */
falcon_drain_tx_fifo ( efx ) ;
2008-04-27 12:55:59 +01:00
}
void falcon_reconfigure_mac_wrapper ( struct efx_nic * efx )
{
2009-11-23 16:06:30 +00:00
struct efx_link_state * link_state = & efx - > link_state ;
2008-04-27 12:55:59 +01:00
efx_oword_t reg ;
int link_speed ;
2009-11-23 16:06:30 +00:00
switch ( link_state - > speed ) {
2008-12-12 21:43:33 -08:00
case 10000 : link_speed = 3 ; break ;
case 1000 : link_speed = 2 ; break ;
case 100 : link_speed = 1 ; break ;
default : link_speed = 0 ; break ;
}
2008-04-27 12:55:59 +01:00
/* MAC_LINK_STATUS controls MAC backpressure but doesn't work
* as advertised . Disable to ensure packets are not
* indefinitely held and TX queue can be flushed at any point
* while the link is down . */
EFX_POPULATE_OWORD_5 ( reg ,
2009-10-23 08:30:36 +00:00
FRF_AB_MAC_XOFF_VAL , 0xffff /* max pause time */ ,
FRF_AB_MAC_BCAD_ACPT , 1 ,
FRF_AB_MAC_UC_PROM , efx - > promiscuous ,
FRF_AB_MAC_LINK_STATUS , 1 , /* always set */
FRF_AB_MAC_SPEED , link_speed ) ;
2008-04-27 12:55:59 +01:00
/* On B0, MAC backpressure can be disabled and packets get
* discarded . */
2009-11-28 05:36:04 +00:00
if ( efx_nic_rev ( efx ) > = EFX_REV_FALCON_B0 ) {
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( reg , FRF_BB_TXFIFO_DRAIN_EN ,
2009-11-23 16:06:30 +00:00
! link_state - > up ) ;
2008-04-27 12:55:59 +01:00
}
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MAC_CTRL ) ;
2008-04-27 12:55:59 +01:00
/* Restore the multicast hash registers. */
2009-11-25 16:12:16 +00:00
falcon_push_multicast_hash ( efx ) ;
2008-04-27 12:55:59 +01:00
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AZ_RX_CFG ) ;
2009-11-29 03:42:18 +00:00
/* Enable XOFF signal from RX FIFO (we enabled it during NIC
* initialisation but it may read back as 0 ) */
EFX_SET_OWORD_FIELD ( reg , FRF_AZ_RX_XOFF_MAC_EN , 1 ) ;
2008-04-27 12:55:59 +01:00
/* Unisolate the MAC -> RX */
2009-11-28 05:36:04 +00:00
if ( efx_nic_rev ( efx ) > = EFX_REV_FALCON_B0 )
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_INGR_EN , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AZ_RX_CFG ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-25 16:11:35 +00:00
static void falcon_stats_request ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
2009-11-25 16:11:35 +00:00
struct falcon_nic_data * nic_data = efx - > nic_data ;
2008-04-27 12:55:59 +01:00
efx_oword_t reg ;
2009-11-25 16:11:35 +00:00
WARN_ON ( nic_data - > stats_pending ) ;
WARN_ON ( nic_data - > stats_disable_count ) ;
2008-04-27 12:55:59 +01:00
2009-11-25 16:11:35 +00:00
if ( nic_data - > stats_dma_done = = NULL )
return ; /* no mac selected */
2008-04-27 12:55:59 +01:00
2009-11-25 16:11:35 +00:00
* nic_data - > stats_dma_done = FALCON_STATS_NOT_DONE ;
nic_data - > stats_pending = true ;
2008-04-27 12:55:59 +01:00
wmb ( ) ; /* ensure done flag is clear */
/* Initiate DMA transfer of stats */
EFX_POPULATE_OWORD_2 ( reg ,
2009-10-23 08:30:36 +00:00
FRF_AB_MAC_STAT_DMA_CMD , 1 ,
FRF_AB_MAC_STAT_DMA_ADR ,
2008-04-27 12:55:59 +01:00
efx - > stats_buffer . dma_addr ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MAC_STAT_DMA ) ;
2008-04-27 12:55:59 +01:00
2009-11-25 16:11:35 +00:00
mod_timer ( & nic_data - > stats_timer , round_jiffies_up ( jiffies + HZ / 2 ) ) ;
}
static void falcon_stats_complete ( struct efx_nic * efx )
{
struct falcon_nic_data * nic_data = efx - > nic_data ;
if ( ! nic_data - > stats_pending )
return ;
nic_data - > stats_pending = 0 ;
if ( * nic_data - > stats_dma_done = = FALCON_STATS_DONE ) {
rmb ( ) ; /* read the done flag before the stats */
efx - > mac_op - > update_stats ( efx ) ;
} else {
EFX_ERR ( efx , " timed out waiting for statistics \n " ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-25 16:11:35 +00:00
}
2008-04-27 12:55:59 +01:00
2009-11-25 16:11:35 +00:00
static void falcon_stats_timer_func ( unsigned long context )
{
struct efx_nic * efx = ( struct efx_nic * ) context ;
struct falcon_nic_data * nic_data = efx - > nic_data ;
spin_lock ( & efx - > stats_lock ) ;
falcon_stats_complete ( efx ) ;
if ( nic_data - > stats_disable_count = = 0 )
falcon_stats_request ( efx ) ;
spin_unlock ( & efx - > stats_lock ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-29 03:42:41 +00:00
static void falcon_switch_mac ( struct efx_nic * efx ) ;
2009-11-28 05:34:05 +00:00
static bool falcon_loopback_link_poll ( struct efx_nic * efx )
{
struct efx_link_state old_state = efx - > link_state ;
WARN_ON ( ! mutex_is_locked ( & efx - > mac_lock ) ) ;
WARN_ON ( ! LOOPBACK_INTERNAL ( efx ) ) ;
efx - > link_state . fd = true ;
efx - > link_state . fc = efx - > wanted_fc ;
efx - > link_state . up = true ;
if ( efx - > loopback_mode = = LOOPBACK_GMAC )
efx - > link_state . speed = 1000 ;
else
efx - > link_state . speed = 10000 ;
return ! efx_link_state_equal ( & efx - > link_state , & old_state ) ;
}
2009-11-29 03:42:41 +00:00
static int falcon_reconfigure_port ( struct efx_nic * efx )
{
int rc ;
WARN_ON ( efx_nic_rev ( efx ) > EFX_REV_FALCON_B0 ) ;
/* Poll the PHY link state *before* reconfiguring it. This means we
* will pick up the correct speed ( in loopback ) to select the correct
* MAC .
*/
if ( LOOPBACK_INTERNAL ( efx ) )
falcon_loopback_link_poll ( efx ) ;
else
efx - > phy_op - > poll ( efx ) ;
falcon_stop_nic_stats ( efx ) ;
falcon_deconfigure_mac_wrapper ( efx ) ;
falcon_switch_mac ( efx ) ;
efx - > phy_op - > reconfigure ( efx ) ;
rc = efx - > mac_op - > reconfigure ( efx ) ;
BUG_ON ( rc ) ;
falcon_start_nic_stats ( efx ) ;
/* Synchronise efx->link_state with the kernel */
efx_link_status_changed ( efx ) ;
return 0 ;
}
2008-04-27 12:55:59 +01:00
/**************************************************************************
*
* PHY access via GMII
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/* Wait for GMII access to complete */
static int falcon_gmii_wait ( struct efx_nic * efx )
{
2009-11-25 16:08:41 +00:00
efx_oword_t md_stat ;
2008-04-27 12:55:59 +01:00
int count ;
2008-12-12 21:50:08 -08:00
/* wait upto 50ms - taken max from datasheet */
for ( count = 0 ; count < 5000 ; count + + ) {
2009-11-25 16:08:41 +00:00
efx_reado ( efx , & md_stat , FR_AB_MD_STAT ) ;
if ( EFX_OWORD_FIELD ( md_stat , FRF_AB_MD_BSY ) = = 0 ) {
if ( EFX_OWORD_FIELD ( md_stat , FRF_AB_MD_LNFL ) ! = 0 | |
EFX_OWORD_FIELD ( md_stat , FRF_AB_MD_BSERR ) ! = 0 ) {
2008-04-27 12:55:59 +01:00
EFX_ERR ( efx , " error from GMII access "
2009-11-25 16:08:41 +00:00
EFX_OWORD_FMT " \n " ,
EFX_OWORD_VAL ( md_stat ) ) ;
2008-04-27 12:55:59 +01:00
return - EIO ;
}
return 0 ;
}
udelay ( 10 ) ;
}
EFX_ERR ( efx , " timed out waiting for GMII \n " ) ;
return - ETIMEDOUT ;
}
2009-04-29 08:05:08 +00:00
/* Write an MDIO register of a PHY connected to Falcon. */
static int falcon_mdio_write ( struct net_device * net_dev ,
int prtad , int devad , u16 addr , u16 value )
2008-04-27 12:55:59 +01:00
{
2008-09-01 12:43:14 +01:00
struct efx_nic * efx = netdev_priv ( net_dev ) ;
2008-04-27 12:55:59 +01:00
efx_oword_t reg ;
2009-04-29 08:05:08 +00:00
int rc ;
2008-04-27 12:55:59 +01:00
2009-04-29 08:05:08 +00:00
EFX_REGDUMP ( efx , " writing MDIO %d register %d.%d with 0x%04x \n " ,
prtad , devad , addr , value ) ;
2008-04-27 12:55:59 +01:00
2009-11-28 05:34:44 +00:00
mutex_lock ( & efx - > mdio_lock ) ;
2008-04-27 12:55:59 +01:00
2009-04-29 08:05:08 +00:00
/* Check MDIO not currently being accessed */
rc = falcon_gmii_wait ( efx ) ;
if ( rc )
2008-04-27 12:55:59 +01:00
goto out ;
/* Write the address/ID register */
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_1 ( reg , FRF_AB_MD_PHY_ADR , addr ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_PHY_ADR ) ;
2008-04-27 12:55:59 +01:00
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_2 ( reg , FRF_AB_MD_PRT_ADR , prtad ,
FRF_AB_MD_DEV_ADR , devad ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_ID ) ;
2008-04-27 12:55:59 +01:00
/* Write data */
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_1 ( reg , FRF_AB_MD_TXD , value ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_TXD ) ;
2008-04-27 12:55:59 +01:00
EFX_POPULATE_OWORD_2 ( reg ,
2009-10-23 08:30:36 +00:00
FRF_AB_MD_WRC , 1 ,
FRF_AB_MD_GC , 0 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_CS ) ;
2008-04-27 12:55:59 +01:00
/* Wait for data to be written */
2009-04-29 08:05:08 +00:00
rc = falcon_gmii_wait ( efx ) ;
if ( rc ) {
2008-04-27 12:55:59 +01:00
/* Abort the write operation */
EFX_POPULATE_OWORD_2 ( reg ,
2009-10-23 08:30:36 +00:00
FRF_AB_MD_WRC , 0 ,
FRF_AB_MD_GC , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_CS ) ;
2008-04-27 12:55:59 +01:00
udelay ( 10 ) ;
}
2009-11-28 05:34:44 +00:00
out :
mutex_unlock ( & efx - > mdio_lock ) ;
2009-04-29 08:05:08 +00:00
return rc ;
2008-04-27 12:55:59 +01:00
}
2009-04-29 08:05:08 +00:00
/* Read an MDIO register of a PHY connected to Falcon. */
static int falcon_mdio_read ( struct net_device * net_dev ,
int prtad , int devad , u16 addr )
2008-04-27 12:55:59 +01:00
{
2008-09-01 12:43:14 +01:00
struct efx_nic * efx = netdev_priv ( net_dev ) ;
2008-04-27 12:55:59 +01:00
efx_oword_t reg ;
2009-04-29 08:05:08 +00:00
int rc ;
2008-04-27 12:55:59 +01:00
2009-11-28 05:34:44 +00:00
mutex_lock ( & efx - > mdio_lock ) ;
2008-04-27 12:55:59 +01:00
2009-04-29 08:05:08 +00:00
/* Check MDIO not currently being accessed */
rc = falcon_gmii_wait ( efx ) ;
if ( rc )
2008-04-27 12:55:59 +01:00
goto out ;
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_1 ( reg , FRF_AB_MD_PHY_ADR , addr ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_PHY_ADR ) ;
2008-04-27 12:55:59 +01:00
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_2 ( reg , FRF_AB_MD_PRT_ADR , prtad ,
FRF_AB_MD_DEV_ADR , devad ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_ID ) ;
2008-04-27 12:55:59 +01:00
/* Request data to be read */
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_2 ( reg , FRF_AB_MD_RDC , 1 , FRF_AB_MD_GC , 0 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_CS ) ;
2008-04-27 12:55:59 +01:00
/* Wait for data to become available */
2009-04-29 08:05:08 +00:00
rc = falcon_gmii_wait ( efx ) ;
if ( rc = = 0 ) {
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AB_MD_RXD ) ;
2009-10-23 08:30:36 +00:00
rc = EFX_OWORD_FIELD ( reg , FRF_AB_MD_RXD ) ;
2009-04-29 08:05:08 +00:00
EFX_REGDUMP ( efx , " read from MDIO %d register %d.%d, got %04x \n " ,
prtad , devad , addr , rc ) ;
2008-04-27 12:55:59 +01:00
} else {
/* Abort the read operation */
EFX_POPULATE_OWORD_2 ( reg ,
2009-10-23 08:30:36 +00:00
FRF_AB_MD_RIC , 0 ,
FRF_AB_MD_GC , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AB_MD_CS ) ;
2008-04-27 12:55:59 +01:00
2009-04-29 08:05:08 +00:00
EFX_LOG ( efx , " read from MDIO %d register %d.%d, got error %d \n " ,
prtad , devad , addr , rc ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-28 05:34:44 +00:00
out :
mutex_unlock ( & efx - > mdio_lock ) ;
2009-04-29 08:05:08 +00:00
return rc ;
2008-04-27 12:55:59 +01:00
}
2009-11-25 16:11:03 +00:00
static void falcon_clock_mac ( struct efx_nic * efx )
{
unsigned strap_val ;
efx_oword_t nic_stat ;
/* Configure the NIC generated MAC clock correctly */
efx_reado ( efx , & nic_stat , FR_AB_NIC_STAT ) ;
strap_val = EFX_IS10G ( efx ) ? 5 : 3 ;
2009-11-28 05:36:04 +00:00
if ( efx_nic_rev ( efx ) > = EFX_REV_FALCON_B0 ) {
2009-11-25 16:11:03 +00:00
EFX_SET_OWORD_FIELD ( nic_stat , FRF_BB_EE_STRAP_EN , 1 ) ;
EFX_SET_OWORD_FIELD ( nic_stat , FRF_BB_EE_STRAP , strap_val ) ;
efx_writeo ( efx , & nic_stat , FR_AB_NIC_STAT ) ;
} else {
/* Falcon A1 does not support 1G/10G speed switching
* and must not be used with a PHY that does . */
BUG_ON ( EFX_OWORD_FIELD ( nic_stat , FRF_AB_STRAP_PINS ) ! =
strap_val ) ;
}
}
2009-11-29 03:42:41 +00:00
static void falcon_switch_mac ( struct efx_nic * efx )
2008-12-12 21:50:08 -08:00
{
struct efx_mac_operations * old_mac_op = efx - > mac_op ;
2009-11-25 16:11:35 +00:00
struct falcon_nic_data * nic_data = efx - > nic_data ;
unsigned int stats_done_offset ;
2008-12-12 21:50:08 -08:00
2009-01-29 17:49:59 +00:00
WARN_ON ( ! mutex_is_locked ( & efx - > mac_lock ) ) ;
2009-11-29 03:42:41 +00:00
WARN_ON ( nic_data - > stats_disable_count = = 0 ) ;
2008-12-12 21:50:08 -08:00
efx - > mac_op = ( EFX_IS10G ( efx ) ?
& falcon_xmac_operations : & falcon_gmac_operations ) ;
2009-11-25 16:11:35 +00:00
if ( EFX_IS10G ( efx ) )
stats_done_offset = XgDmaDone_offset ;
else
stats_done_offset = GDmaDone_offset ;
nic_data - > stats_dma_done = efx - > stats_buffer . addr + stats_done_offset ;
2009-01-29 17:49:59 +00:00
if ( old_mac_op = = efx - > mac_op )
2009-11-29 03:42:41 +00:00
return ;
2008-12-12 21:50:08 -08:00
2009-11-25 16:11:03 +00:00
falcon_clock_mac ( efx ) ;
2008-12-12 21:50:08 -08:00
EFX_LOG ( efx , " selected %cMAC \n " , EFX_IS10G ( efx ) ? ' X ' : ' G ' ) ;
2009-01-29 17:49:59 +00:00
/* Not all macs support a mac-level link state */
2009-11-25 16:12:01 +00:00
efx - > xmac_poll_required = false ;
2009-11-29 03:42:41 +00:00
falcon_reset_macs ( efx ) ;
2008-12-12 21:50:08 -08:00
}
2008-04-27 12:55:59 +01:00
/* This call is responsible for hooking in the MAC and PHY operations */
2009-11-29 03:42:31 +00:00
static int falcon_probe_port ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
int rc ;
2009-10-23 08:32:42 +00:00
switch ( efx - > phy_type ) {
case PHY_TYPE_SFX7101 :
efx - > phy_op = & falcon_sfx7101_phy_ops ;
break ;
case PHY_TYPE_SFT9001A :
case PHY_TYPE_SFT9001B :
efx - > phy_op = & falcon_sft9001_phy_ops ;
break ;
case PHY_TYPE_QT2022C2 :
case PHY_TYPE_QT2025C :
2009-10-23 08:33:42 +00:00
efx - > phy_op = & falcon_qt202x_phy_ops ;
2009-10-23 08:32:42 +00:00
break ;
default :
EFX_ERR ( efx , " Unknown PHY type %d \n " ,
efx - > phy_type ) ;
return - ENODEV ;
}
2009-11-29 15:08:55 +00:00
/* Fill out MDIO structure and loopback modes */
2009-04-29 08:05:08 +00:00
efx - > mdio . mdio_read = falcon_mdio_read ;
efx - > mdio . mdio_write = falcon_mdio_write ;
2009-11-29 15:08:55 +00:00
rc = efx - > phy_op - > probe ( efx ) ;
if ( rc ! = 0 )
return rc ;
2008-04-27 12:55:59 +01:00
2009-11-28 05:35:00 +00:00
/* Initial assumption */
efx - > link_state . speed = 10000 ;
efx - > link_state . fd = true ;
2008-04-27 12:55:59 +01:00
/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
2009-11-28 05:36:04 +00:00
if ( efx_nic_rev ( efx ) > = EFX_REV_FALCON_B0 )
2008-12-12 21:50:46 -08:00
efx - > wanted_fc = EFX_FC_RX | EFX_FC_TX ;
2008-04-27 12:55:59 +01:00
else
2008-12-12 21:50:46 -08:00
efx - > wanted_fc = EFX_FC_RX ;
2008-04-27 12:55:59 +01:00
/* Allocate buffer for stats */
2009-11-29 03:43:56 +00:00
rc = efx_nic_alloc_buffer ( efx , & efx - > stats_buffer ,
FALCON_MAC_STATS_SIZE ) ;
2008-04-27 12:55:59 +01:00
if ( rc )
return rc ;
2009-02-11 23:49:52 +05:30
EFX_LOG ( efx , " stats buffer at %llx (virt %p phys %llx) \n " ,
( u64 ) efx - > stats_buffer . dma_addr ,
2008-04-27 12:55:59 +01:00
efx - > stats_buffer . addr ,
2009-02-11 23:49:52 +05:30
( u64 ) virt_to_phys ( efx - > stats_buffer . addr ) ) ;
2008-04-27 12:55:59 +01:00
return 0 ;
}
2009-11-29 03:42:31 +00:00
static void falcon_remove_port ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
2009-11-29 03:43:56 +00:00
efx_nic_free_buffer ( efx , & efx - > stats_buffer ) ;
2008-04-27 12:55:59 +01:00
}
2008-09-01 12:49:02 +01:00
/**************************************************************************
*
* Falcon test code
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-11-29 03:43:33 +00:00
static int
falcon_read_nvram ( struct efx_nic * efx , struct falcon_nvconfig * nvconfig_out )
2008-09-01 12:49:02 +01:00
{
struct falcon_nvconfig * nvconfig ;
struct efx_spi_device * spi ;
void * region ;
int rc , magic_num , struct_ver ;
__le16 * word , * limit ;
u32 csum ;
2008-12-12 21:34:25 -08:00
spi = efx - > spi_flash ? efx - > spi_flash : efx - > spi_eeprom ;
if ( ! spi )
return - EINVAL ;
2008-11-04 20:33:11 +00:00
region = kmalloc ( FALCON_NVCONFIG_END , GFP_KERNEL ) ;
2008-09-01 12:49:02 +01:00
if ( ! region )
return - ENOMEM ;
2009-10-23 08:30:36 +00:00
nvconfig = region + FALCON_NVCONFIG_OFFSET ;
2008-09-01 12:49:02 +01:00
2008-11-04 20:34:28 +00:00
mutex_lock ( & efx - > spi_lock ) ;
2009-11-29 15:10:44 +00:00
rc = falcon_spi_read ( efx , spi , 0 , FALCON_NVCONFIG_END , NULL , region ) ;
2008-11-04 20:34:28 +00:00
mutex_unlock ( & efx - > spi_lock ) ;
2008-09-01 12:49:02 +01:00
if ( rc ) {
EFX_ERR ( efx , " Failed to read %s \n " ,
efx - > spi_flash ? " flash " : " EEPROM " ) ;
rc = - EIO ;
goto out ;
}
magic_num = le16_to_cpu ( nvconfig - > board_magic_num ) ;
struct_ver = le16_to_cpu ( nvconfig - > board_struct_ver ) ;
rc = - EINVAL ;
2009-10-23 08:30:36 +00:00
if ( magic_num ! = FALCON_NVCONFIG_BOARD_MAGIC_NUM ) {
2008-09-01 12:49:02 +01:00
EFX_ERR ( efx , " NVRAM bad magic 0x%x \n " , magic_num ) ;
goto out ;
}
if ( struct_ver < 2 ) {
EFX_ERR ( efx , " NVRAM has ancient version 0x%x \n " , struct_ver ) ;
goto out ;
} else if ( struct_ver < 4 ) {
word = & nvconfig - > board_magic_num ;
limit = ( __le16 * ) ( nvconfig + 1 ) ;
} else {
word = region ;
2008-11-04 20:33:11 +00:00
limit = region + FALCON_NVCONFIG_END ;
2008-09-01 12:49:02 +01:00
}
for ( csum = 0 ; word < limit ; + + word )
csum + = le16_to_cpu ( * word ) ;
if ( ~ csum & 0xffff ) {
EFX_ERR ( efx , " NVRAM has incorrect checksum \n " ) ;
goto out ;
}
rc = 0 ;
if ( nvconfig_out )
memcpy ( nvconfig_out , nvconfig , sizeof ( * nvconfig ) ) ;
out :
kfree ( region ) ;
return rc ;
}
2009-11-29 03:43:33 +00:00
static int falcon_test_nvram ( struct efx_nic * efx )
{
return falcon_read_nvram ( efx , NULL ) ;
}
2009-11-29 03:43:56 +00:00
static const struct efx_nic_register_test falcon_b0_register_tests [ ] = {
2009-10-23 08:30:36 +00:00
{ FR_AZ_ADR_REGION ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x0001FFFF , 0x0001FFFF , 0x0001FFFF , 0x0001FFFF ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AZ_RX_CFG ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0xFFFFFFFE , 0x00017FFF , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AZ_TX_CFG ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x7FFF0037 , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AZ_TX_RESERVED ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0xFFFEFE80 , 0x1FFFFFFF , 0x020000FE , 0x007FFFFF ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_MAC_CTRL ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0xFFFF0000 , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AZ_SRM_TX_DC_CFG ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x001FFFFF , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AZ_RX_DC_CFG ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x0000000F , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AZ_RX_DC_PF_WM ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x000003FF , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_BZ_DP_CTRL ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x00000FFF , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_GM_CFG2 ,
2008-12-12 21:50:08 -08:00
EFX_OWORD32 ( 0x00007337 , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_GMF_CFG0 ,
2008-12-12 21:50:08 -08:00
EFX_OWORD32 ( 0x00001F1F , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_XM_GLB_CFG ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x00000C68 , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_XM_TX_CFG ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x00080164 , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_XM_RX_CFG ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x07100A0C , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_XM_RX_PARAM ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x00001FF8 , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_XM_FC ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0xFFFF0001 , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_XM_ADR_LO ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0xFFFFFFFF , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
2009-10-23 08:30:36 +00:00
{ FR_AB_XX_SD_CTL ,
2008-09-01 12:49:02 +01:00
EFX_OWORD32 ( 0x0003FF0F , 0x00000000 , 0x00000000 , 0x00000000 ) } ,
} ;
2009-11-29 03:43:56 +00:00
static int falcon_b0_test_registers ( struct efx_nic * efx )
{
return efx_nic_test_registers ( efx , falcon_b0_register_tests ,
ARRAY_SIZE ( falcon_b0_register_tests ) ) ;
}
2008-04-27 12:55:59 +01:00
/**************************************************************************
*
* Device reset
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/* Resets NIC to known state. This routine must be called in process
* context and is allowed to sleep . */
2009-11-29 03:42:31 +00:00
static int falcon_reset_hw ( struct efx_nic * efx , enum reset_type method )
2008-04-27 12:55:59 +01:00
{
struct falcon_nic_data * nic_data = efx - > nic_data ;
efx_oword_t glb_ctl_reg_ker ;
int rc ;
2009-11-23 16:08:17 +00:00
EFX_LOG ( efx , " performing %s hardware reset \n " , RESET_TYPE ( method ) ) ;
2008-04-27 12:55:59 +01:00
/* Initiate device reset */
if ( method = = RESET_TYPE_WORLD ) {
rc = pci_save_state ( efx - > pci_dev ) ;
if ( rc ) {
EFX_ERR ( efx , " failed to backup PCI state of primary "
" function prior to hardware reset \n " ) ;
goto fail1 ;
}
2009-11-29 03:43:56 +00:00
if ( efx_nic_is_dual_func ( efx ) ) {
2008-04-27 12:55:59 +01:00
rc = pci_save_state ( nic_data - > pci_dev2 ) ;
if ( rc ) {
EFX_ERR ( efx , " failed to backup PCI state of "
" secondary function prior to "
" hardware reset \n " ) ;
goto fail2 ;
}
}
EFX_POPULATE_OWORD_2 ( glb_ctl_reg_ker ,
2009-10-23 08:30:36 +00:00
FRF_AB_EXT_PHY_RST_DUR ,
FFE_AB_EXT_PHY_RST_DUR_10240US ,
FRF_AB_SWRST , 1 ) ;
2008-04-27 12:55:59 +01:00
} else {
EFX_POPULATE_OWORD_7 ( glb_ctl_reg_ker ,
2009-10-23 08:30:36 +00:00
/* exclude PHY from "invisible" reset */
FRF_AB_EXT_PHY_RST_CTL ,
method = = RESET_TYPE_INVISIBLE ,
/* exclude EEPROM/flash and PCIe */
FRF_AB_PCIE_CORE_RST_CTL , 1 ,
FRF_AB_PCIE_NSTKY_RST_CTL , 1 ,
FRF_AB_PCIE_SD_RST_CTL , 1 ,
FRF_AB_EE_RST_CTL , 1 ,
FRF_AB_EXT_PHY_RST_DUR ,
FFE_AB_EXT_PHY_RST_DUR_10240US ,
FRF_AB_SWRST , 1 ) ;
}
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & glb_ctl_reg_ker , FR_AB_GLB_CTL ) ;
2008-04-27 12:55:59 +01:00
EFX_LOG ( efx , " waiting for hardware reset \n " ) ;
schedule_timeout_uninterruptible ( HZ / 20 ) ;
/* Restore PCI configuration if needed */
if ( method = = RESET_TYPE_WORLD ) {
2009-11-29 03:43:56 +00:00
if ( efx_nic_is_dual_func ( efx ) ) {
2008-04-27 12:55:59 +01:00
rc = pci_restore_state ( nic_data - > pci_dev2 ) ;
if ( rc ) {
EFX_ERR ( efx , " failed to restore PCI config for "
" the secondary function \n " ) ;
goto fail3 ;
}
}
rc = pci_restore_state ( efx - > pci_dev ) ;
if ( rc ) {
EFX_ERR ( efx , " failed to restore PCI config for the "
" primary function \n " ) ;
goto fail4 ;
}
EFX_LOG ( efx , " successfully restored PCI config \n " ) ;
}
/* Assert that reset complete */
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & glb_ctl_reg_ker , FR_AB_GLB_CTL ) ;
2009-10-23 08:30:36 +00:00
if ( EFX_OWORD_FIELD ( glb_ctl_reg_ker , FRF_AB_SWRST ) ! = 0 ) {
2008-04-27 12:55:59 +01:00
rc = - ETIMEDOUT ;
EFX_ERR ( efx , " timed out waiting for hardware reset \n " ) ;
goto fail5 ;
}
EFX_LOG ( efx , " hardware reset complete \n " ) ;
return 0 ;
/* pci_save_state() and pci_restore_state() MUST be called in pairs */
fail2 :
fail3 :
pci_restore_state ( efx - > pci_dev ) ;
fail1 :
fail4 :
fail5 :
return rc ;
}
2009-11-29 03:42:31 +00:00
static void falcon_monitor ( struct efx_nic * efx )
2009-11-25 16:11:45 +00:00
{
2009-11-28 05:34:05 +00:00
bool link_changed ;
2009-11-25 16:11:45 +00:00
int rc ;
2009-11-28 05:34:05 +00:00
BUG_ON ( ! mutex_is_locked ( & efx - > mac_lock ) ) ;
2009-11-25 16:11:45 +00:00
rc = falcon_board ( efx ) - > type - > monitor ( efx ) ;
if ( rc ) {
EFX_ERR ( efx , " Board sensor %s; shutting down PHY \n " ,
( rc = = - ERANGE ) ? " reported fault " : " failed " ) ;
efx - > phy_mode | = PHY_MODE_LOW_POWER ;
2009-11-29 03:42:41 +00:00
rc = __efx_reconfigure_port ( efx ) ;
WARN_ON ( rc ) ;
2009-11-25 16:11:45 +00:00
}
2009-11-28 05:34:05 +00:00
if ( LOOPBACK_INTERNAL ( efx ) )
link_changed = falcon_loopback_link_poll ( efx ) ;
else
link_changed = efx - > phy_op - > poll ( efx ) ;
if ( link_changed ) {
falcon_stop_nic_stats ( efx ) ;
falcon_deconfigure_mac_wrapper ( efx ) ;
falcon_switch_mac ( efx ) ;
2009-11-29 03:42:41 +00:00
rc = efx - > mac_op - > reconfigure ( efx ) ;
BUG_ON ( rc ) ;
2009-11-28 05:34:05 +00:00
falcon_start_nic_stats ( efx ) ;
efx_link_status_changed ( efx ) ;
}
2009-11-25 16:12:01 +00:00
if ( EFX_IS10G ( efx ) )
falcon_poll_xmac ( efx ) ;
2009-11-25 16:11:45 +00:00
}
2008-04-27 12:55:59 +01:00
/* Zeroes out the SRAM contents. This routine must be called in
* process context and is allowed to sleep .
*/
static int falcon_reset_sram ( struct efx_nic * efx )
{
efx_oword_t srm_cfg_reg_ker , gpio_cfg_reg_ker ;
int count ;
/* Set the SRAM wake/sleep GPIO appropriately. */
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & gpio_cfg_reg_ker , FR_AB_GPIO_CTL ) ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( gpio_cfg_reg_ker , FRF_AB_GPIO1_OEN , 1 ) ;
EFX_SET_OWORD_FIELD ( gpio_cfg_reg_ker , FRF_AB_GPIO1_OUT , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & gpio_cfg_reg_ker , FR_AB_GPIO_CTL ) ;
2008-04-27 12:55:59 +01:00
/* Initiate SRAM reset */
EFX_POPULATE_OWORD_2 ( srm_cfg_reg_ker ,
2009-10-23 08:30:36 +00:00
FRF_AZ_SRM_INIT_EN , 1 ,
FRF_AZ_SRM_NB_SZ , 0 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & srm_cfg_reg_ker , FR_AZ_SRM_CFG ) ;
2008-04-27 12:55:59 +01:00
/* Wait for SRAM reset to complete */
count = 0 ;
do {
EFX_LOG ( efx , " waiting for SRAM reset (attempt %d)... \n " , count ) ;
/* SRAM reset is slow; expect around 16ms */
schedule_timeout_uninterruptible ( HZ / 50 ) ;
/* Check for reset complete */
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & srm_cfg_reg_ker , FR_AZ_SRM_CFG ) ;
2009-10-23 08:30:36 +00:00
if ( ! EFX_OWORD_FIELD ( srm_cfg_reg_ker , FRF_AZ_SRM_INIT_EN ) ) {
2008-04-27 12:55:59 +01:00
EFX_LOG ( efx , " SRAM reset complete \n " ) ;
return 0 ;
}
} while ( + + count < 20 ) ; /* wait upto 0.4 sec */
EFX_ERR ( efx , " timed out waiting for SRAM reset \n " ) ;
return - ETIMEDOUT ;
}
2008-09-01 12:47:16 +01:00
static int falcon_spi_device_init ( struct efx_nic * efx ,
struct efx_spi_device * * spi_device_ret ,
unsigned int device_id , u32 device_type )
{
struct efx_spi_device * spi_device ;
if ( device_type ! = 0 ) {
2008-12-12 22:08:50 -08:00
spi_device = kzalloc ( sizeof ( * spi_device ) , GFP_KERNEL ) ;
2008-09-01 12:47:16 +01:00
if ( ! spi_device )
return - ENOMEM ;
spi_device - > device_id = device_id ;
spi_device - > size =
1 < < SPI_DEV_TYPE_FIELD ( device_type , SPI_DEV_TYPE_SIZE ) ;
spi_device - > addr_len =
SPI_DEV_TYPE_FIELD ( device_type , SPI_DEV_TYPE_ADDR_LEN ) ;
spi_device - > munge_address = ( spi_device - > size = = 1 < < 9 & &
spi_device - > addr_len = = 1 ) ;
2008-11-04 20:34:28 +00:00
spi_device - > erase_command =
SPI_DEV_TYPE_FIELD ( device_type , SPI_DEV_TYPE_ERASE_CMD ) ;
spi_device - > erase_size =
1 < < SPI_DEV_TYPE_FIELD ( device_type ,
SPI_DEV_TYPE_ERASE_SIZE ) ;
2008-09-01 12:47:16 +01:00
spi_device - > block_size =
1 < < SPI_DEV_TYPE_FIELD ( device_type ,
SPI_DEV_TYPE_BLOCK_SIZE ) ;
} else {
spi_device = NULL ;
}
kfree ( * spi_device_ret ) ;
* spi_device_ret = spi_device ;
return 0 ;
}
static void falcon_remove_spi_devices ( struct efx_nic * efx )
{
kfree ( efx - > spi_eeprom ) ;
efx - > spi_eeprom = NULL ;
kfree ( efx - > spi_flash ) ;
efx - > spi_flash = NULL ;
}
2008-04-27 12:55:59 +01:00
/* Extract non-volatile configuration */
static int falcon_probe_nvconfig ( struct efx_nic * efx )
{
struct falcon_nvconfig * nvconfig ;
2008-09-01 12:49:02 +01:00
int board_rev ;
2008-04-27 12:55:59 +01:00
int rc ;
nvconfig = kmalloc ( sizeof ( * nvconfig ) , GFP_KERNEL ) ;
2008-09-01 12:47:16 +01:00
if ( ! nvconfig )
return - ENOMEM ;
2008-04-27 12:55:59 +01:00
2008-09-01 12:49:02 +01:00
rc = falcon_read_nvram ( efx , nvconfig ) ;
if ( rc = = - EINVAL ) {
EFX_ERR ( efx , " NVRAM is invalid therefore using defaults \n " ) ;
2008-04-27 12:55:59 +01:00
efx - > phy_type = PHY_TYPE_NONE ;
2009-04-29 08:05:08 +00:00
efx - > mdio . prtad = MDIO_PRTAD_NONE ;
2008-04-27 12:55:59 +01:00
board_rev = 0 ;
2008-09-01 12:49:02 +01:00
rc = 0 ;
} else if ( rc ) {
goto fail1 ;
2008-04-27 12:55:59 +01:00
} else {
struct falcon_nvconfig_board_v2 * v2 = & nvconfig - > board_v2 ;
2008-09-01 12:47:16 +01:00
struct falcon_nvconfig_board_v3 * v3 = & nvconfig - > board_v3 ;
2008-04-27 12:55:59 +01:00
efx - > phy_type = v2 - > port0_phy_type ;
2009-04-29 08:05:08 +00:00
efx - > mdio . prtad = v2 - > port0_phy_addr ;
2008-04-27 12:55:59 +01:00
board_rev = le16_to_cpu ( v2 - > board_revision ) ;
2008-09-01 12:47:16 +01:00
2008-09-01 12:49:02 +01:00
if ( le16_to_cpu ( nvconfig - > board_struct_ver ) > = 3 ) {
2009-10-23 08:30:36 +00:00
rc = falcon_spi_device_init (
efx , & efx - > spi_flash , FFE_AB_SPI_DEVICE_FLASH ,
le32_to_cpu ( v3 - > spi_device_type
[ FFE_AB_SPI_DEVICE_FLASH ] ) ) ;
2008-09-01 12:47:16 +01:00
if ( rc )
goto fail2 ;
2009-10-23 08:30:36 +00:00
rc = falcon_spi_device_init (
efx , & efx - > spi_eeprom , FFE_AB_SPI_DEVICE_EEPROM ,
le32_to_cpu ( v3 - > spi_device_type
[ FFE_AB_SPI_DEVICE_EEPROM ] ) ) ;
2008-09-01 12:47:16 +01:00
if ( rc )
goto fail2 ;
}
2008-04-27 12:55:59 +01:00
}
2008-09-01 12:49:02 +01:00
/* Read the MAC addresses */
memcpy ( efx - > mac_address , nvconfig - > mac_address [ 0 ] , ETH_ALEN ) ;
2009-04-29 08:05:08 +00:00
EFX_LOG ( efx , " PHY is %d phy_id %d \n " , efx - > phy_type , efx - > mdio . prtad ) ;
2008-04-27 12:55:59 +01:00
2009-10-23 08:29:16 +00:00
falcon_probe_board ( efx , board_rev ) ;
2008-04-27 12:55:59 +01:00
2008-09-01 12:47:16 +01:00
kfree ( nvconfig ) ;
return 0 ;
fail2 :
falcon_remove_spi_devices ( efx ) ;
fail1 :
2008-04-27 12:55:59 +01:00
kfree ( nvconfig ) ;
return rc ;
}
2008-09-01 12:47:16 +01:00
/* Probe all SPI devices on the NIC */
static void falcon_probe_spi_devices ( struct efx_nic * efx )
{
efx_oword_t nic_stat , gpio_ctl , ee_vpd_cfg ;
2008-12-12 21:34:25 -08:00
int boot_dev ;
2008-09-01 12:47:16 +01:00
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & gpio_ctl , FR_AB_GPIO_CTL ) ;
efx_reado ( efx , & nic_stat , FR_AB_NIC_STAT ) ;
efx_reado ( efx , & ee_vpd_cfg , FR_AB_EE_VPD_CFG0 ) ;
2008-09-01 12:47:16 +01:00
2009-10-23 08:30:36 +00:00
if ( EFX_OWORD_FIELD ( gpio_ctl , FRF_AB_GPIO3_PWRUP_VALUE ) ) {
boot_dev = ( EFX_OWORD_FIELD ( nic_stat , FRF_AB_SF_PRST ) ?
FFE_AB_SPI_DEVICE_FLASH : FFE_AB_SPI_DEVICE_EEPROM ) ;
2008-12-12 21:34:25 -08:00
EFX_LOG ( efx , " Booted from %s \n " ,
2009-10-23 08:30:36 +00:00
boot_dev = = FFE_AB_SPI_DEVICE_FLASH ? " flash " : " EEPROM " ) ;
2008-12-12 21:34:25 -08:00
} else {
/* Disable VPD and set clock dividers to safe
* values for initial programming . */
boot_dev = - 1 ;
EFX_LOG ( efx , " Booted from internal ASIC settings; "
" setting SPI config \n " ) ;
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_3 ( ee_vpd_cfg , FRF_AB_EE_VPD_EN , 0 ,
2008-12-12 21:34:25 -08:00
/* 125 MHz / 7 ~= 20 MHz */
2009-10-23 08:30:36 +00:00
FRF_AB_EE_SF_CLOCK_DIV , 7 ,
2008-12-12 21:34:25 -08:00
/* 125 MHz / 63 ~= 2 MHz */
2009-10-23 08:30:36 +00:00
FRF_AB_EE_EE_CLOCK_DIV , 63 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & ee_vpd_cfg , FR_AB_EE_VPD_CFG0 ) ;
2008-09-01 12:47:16 +01:00
}
2009-10-23 08:30:36 +00:00
if ( boot_dev = = FFE_AB_SPI_DEVICE_FLASH )
falcon_spi_device_init ( efx , & efx - > spi_flash ,
FFE_AB_SPI_DEVICE_FLASH ,
2008-12-12 21:34:25 -08:00
default_flash_type ) ;
2009-10-23 08:30:36 +00:00
if ( boot_dev = = FFE_AB_SPI_DEVICE_EEPROM )
falcon_spi_device_init ( efx , & efx - > spi_eeprom ,
FFE_AB_SPI_DEVICE_EEPROM ,
2008-12-12 21:34:25 -08:00
large_eeprom_type ) ;
2008-09-01 12:47:16 +01:00
}
2009-11-29 03:42:31 +00:00
static int falcon_probe_nic ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
struct falcon_nic_data * nic_data ;
2009-11-23 16:06:02 +00:00
struct falcon_board * board ;
2008-04-27 12:55:59 +01:00
int rc ;
/* Allocate storage for hardware specific data */
nic_data = kzalloc ( sizeof ( * nic_data ) , GFP_KERNEL ) ;
2008-09-03 15:07:50 +01:00
if ( ! nic_data )
return - ENOMEM ;
2008-05-16 21:19:43 +01:00
efx - > nic_data = nic_data ;
2008-04-27 12:55:59 +01:00
2009-11-29 15:08:21 +00:00
rc = - ENODEV ;
if ( efx_nic_fpga_ver ( efx ) ! = 0 ) {
EFX_ERR ( efx , " Falcon FPGA not supported \n " ) ;
2008-04-27 12:55:59 +01:00
goto fail1 ;
2009-11-29 15:08:21 +00:00
}
if ( efx_nic_rev ( efx ) < = EFX_REV_FALCON_A1 ) {
efx_oword_t nic_stat ;
struct pci_dev * dev ;
u8 pci_rev = efx - > pci_dev - > revision ;
2008-04-27 12:55:59 +01:00
2009-11-29 15:08:21 +00:00
if ( ( pci_rev = = 0xff ) | | ( pci_rev = = 0 ) ) {
EFX_ERR ( efx , " Falcon rev A0 not supported \n " ) ;
goto fail1 ;
}
efx_reado ( efx , & nic_stat , FR_AB_NIC_STAT ) ;
if ( EFX_OWORD_FIELD ( nic_stat , FRF_AB_STRAP_10G ) = = 0 ) {
EFX_ERR ( efx , " Falcon rev A1 1G not supported \n " ) ;
goto fail1 ;
}
if ( EFX_OWORD_FIELD ( nic_stat , FRF_AA_STRAP_PCIE ) = = 0 ) {
EFX_ERR ( efx , " Falcon rev A1 PCI-X not supported \n " ) ;
goto fail1 ;
}
2008-04-27 12:55:59 +01:00
2009-11-29 15:08:21 +00:00
dev = pci_dev_get ( efx - > pci_dev ) ;
2008-04-27 12:55:59 +01:00
while ( ( dev = pci_get_device ( EFX_VENDID_SFC , FALCON_A_S_DEVID ,
dev ) ) ) {
if ( dev - > bus = = efx - > pci_dev - > bus & &
dev - > devfn = = efx - > pci_dev - > devfn + 1 ) {
nic_data - > pci_dev2 = dev ;
break ;
}
}
if ( ! nic_data - > pci_dev2 ) {
EFX_ERR ( efx , " failed to find secondary function \n " ) ;
rc = - ENODEV ;
goto fail2 ;
}
}
/* Now we can reset the NIC */
rc = falcon_reset_hw ( efx , RESET_TYPE_ALL ) ;
if ( rc ) {
EFX_ERR ( efx , " failed to reset NIC \n " ) ;
goto fail3 ;
}
/* Allocate memory for INT_KER */
2009-11-29 03:43:56 +00:00
rc = efx_nic_alloc_buffer ( efx , & efx - > irq_status , sizeof ( efx_oword_t ) ) ;
2008-04-27 12:55:59 +01:00
if ( rc )
goto fail4 ;
BUG_ON ( efx - > irq_status . dma_addr & 0x0f ) ;
2009-02-11 23:49:52 +05:30
EFX_LOG ( efx , " INT_KER at %llx (virt %p phys %llx) \n " ,
( u64 ) efx - > irq_status . dma_addr ,
efx - > irq_status . addr , ( u64 ) virt_to_phys ( efx - > irq_status . addr ) ) ;
2008-04-27 12:55:59 +01:00
2008-09-01 12:47:16 +01:00
falcon_probe_spi_devices ( efx ) ;
2008-04-27 12:55:59 +01:00
/* Read in the non-volatile configuration */
rc = falcon_probe_nvconfig ( efx ) ;
if ( rc )
goto fail5 ;
2008-05-30 22:27:04 +01:00
/* Initialise I2C adapter */
2009-11-23 16:06:02 +00:00
board = falcon_board ( efx ) ;
board - > i2c_adap . owner = THIS_MODULE ;
board - > i2c_data = falcon_i2c_bit_operations ;
board - > i2c_data . data = efx ;
board - > i2c_adap . algo_data = & board - > i2c_data ;
board - > i2c_adap . dev . parent = & efx - > pci_dev - > dev ;
strlcpy ( board - > i2c_adap . name , " SFC4000 GPIO " ,
sizeof ( board - > i2c_adap . name ) ) ;
rc = i2c_bit_add_bus ( & board - > i2c_adap ) ;
2008-05-30 22:27:04 +01:00
if ( rc )
goto fail5 ;
2009-11-25 16:09:41 +00:00
rc = falcon_board ( efx ) - > type - > init ( efx ) ;
2009-11-23 16:05:12 +00:00
if ( rc ) {
EFX_ERR ( efx , " failed to initialise board \n " ) ;
goto fail6 ;
}
2009-11-25 16:11:35 +00:00
nic_data - > stats_disable_count = 1 ;
setup_timer ( & nic_data - > stats_timer , & falcon_stats_timer_func ,
( unsigned long ) efx ) ;
2008-04-27 12:55:59 +01:00
return 0 ;
2009-11-23 16:05:12 +00:00
fail6 :
2009-11-23 16:06:02 +00:00
BUG_ON ( i2c_del_adapter ( & board - > i2c_adap ) ) ;
memset ( & board - > i2c_adap , 0 , sizeof ( board - > i2c_adap ) ) ;
2008-04-27 12:55:59 +01:00
fail5 :
2008-09-01 12:47:16 +01:00
falcon_remove_spi_devices ( efx ) ;
2009-11-29 03:43:56 +00:00
efx_nic_free_buffer ( efx , & efx - > irq_status ) ;
2008-04-27 12:55:59 +01:00
fail4 :
fail3 :
if ( nic_data - > pci_dev2 ) {
pci_dev_put ( nic_data - > pci_dev2 ) ;
nic_data - > pci_dev2 = NULL ;
}
fail2 :
fail1 :
kfree ( efx - > nic_data ) ;
return rc ;
}
2009-10-23 08:30:06 +00:00
static void falcon_init_rx_cfg ( struct efx_nic * efx )
{
/* Prior to Siena the RX DMA engine will split each frame at
* intervals of RX_USR_BUF_SIZE ( 32 - byte units ) . We set it to
* be so large that that never happens . */
const unsigned huge_buf_size = ( 3 * 4096 ) > > 5 ;
/* RX control FIFO thresholds (32 entries) */
const unsigned ctrl_xon_thr = 20 ;
const unsigned ctrl_xoff_thr = 25 ;
/* RX data FIFO thresholds (256-byte units; size varies) */
2009-11-29 03:43:56 +00:00
int data_xon_thr = efx_nic_rx_xon_thresh > > 8 ;
int data_xoff_thr = efx_nic_rx_xoff_thresh > > 8 ;
2009-10-23 08:30:06 +00:00
efx_oword_t reg ;
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & reg , FR_AZ_RX_CFG ) ;
2009-11-28 05:36:04 +00:00
if ( efx_nic_rev ( efx ) < = EFX_REV_FALCON_A1 ) {
2009-10-23 08:30:17 +00:00
/* Data FIFO size is 5.5K */
if ( data_xon_thr < 0 )
data_xon_thr = 512 > > 8 ;
if ( data_xoff_thr < 0 )
data_xoff_thr = 2048 > > 8 ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( reg , FRF_AA_RX_DESC_PUSH_EN , 0 ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_AA_RX_USR_BUF_SIZE ,
huge_buf_size ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_AA_RX_XON_MAC_TH , data_xon_thr ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_AA_RX_XOFF_MAC_TH , data_xoff_thr ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_AA_RX_XON_TX_TH , ctrl_xon_thr ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_AA_RX_XOFF_TX_TH , ctrl_xoff_thr ) ;
2009-10-23 08:30:06 +00:00
} else {
2009-10-23 08:30:17 +00:00
/* Data FIFO size is 80K; register fields moved */
if ( data_xon_thr < 0 )
data_xon_thr = 27648 > > 8 ; /* ~3*max MTU */
if ( data_xoff_thr < 0 )
data_xoff_thr = 54272 > > 8 ; /* ~80Kb - 3*max MTU */
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_DESC_PUSH_EN , 0 ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_USR_BUF_SIZE ,
huge_buf_size ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_XON_MAC_TH , data_xon_thr ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_XOFF_MAC_TH , data_xoff_thr ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_XON_TX_TH , ctrl_xon_thr ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_XOFF_TX_TH , ctrl_xoff_thr ) ;
EFX_SET_OWORD_FIELD ( reg , FRF_BZ_RX_INGR_EN , 1 ) ;
2009-10-23 08:30:06 +00:00
}
2009-11-29 03:42:18 +00:00
/* Always enable XOFF signal from RX FIFO. We enable
* or disable transmission of pause frames at the MAC . */
EFX_SET_OWORD_FIELD ( reg , FRF_AZ_RX_XOFF_MAC_EN , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & reg , FR_AZ_RX_CFG ) ;
2009-10-23 08:30:06 +00:00
}
2009-11-29 03:43:56 +00:00
/* This call performs hardware-specific global initialisation, such as
* defining the descriptor cache sizes and number of RSS channels .
* It does not set up any buffers , descriptor rings or event queues .
*/
static int falcon_init_nic ( struct efx_nic * efx )
{
efx_oword_t temp ;
int rc ;
/* Use on-chip SRAM */
efx_reado ( efx , & temp , FR_AB_NIC_STAT ) ;
EFX_SET_OWORD_FIELD ( temp , FRF_AB_ONCHIP_SRAM , 1 ) ;
efx_writeo ( efx , & temp , FR_AB_NIC_STAT ) ;
/* Set the source of the GMAC clock */
if ( efx_nic_rev ( efx ) = = EFX_REV_FALCON_B0 ) {
efx_reado ( efx , & temp , FR_AB_GPIO_CTL ) ;
EFX_SET_OWORD_FIELD ( temp , FRF_AB_USE_NIC_CLK , true ) ;
efx_writeo ( efx , & temp , FR_AB_GPIO_CTL ) ;
}
/* Select the correct MAC */
falcon_clock_mac ( efx ) ;
rc = falcon_reset_sram ( efx ) ;
if ( rc )
return rc ;
/* Clear the parity enables on the TX data fifos as
* they produce false parity errors because of timing issues
*/
if ( EFX_WORKAROUND_5129 ( efx ) ) {
efx_reado ( efx , & temp , FR_AZ_CSR_SPARE ) ;
EFX_SET_OWORD_FIELD ( temp , FRF_AB_MEM_PERR_EN_TX_DATA , 0 ) ;
efx_writeo ( efx , & temp , FR_AZ_CSR_SPARE ) ;
}
2008-04-27 12:55:59 +01:00
if ( EFX_WORKAROUND_7244 ( efx ) ) {
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & temp , FR_BZ_RX_FILTER_CTL ) ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( temp , FRF_BZ_UDP_FULL_SRCH_LIMIT , 8 ) ;
EFX_SET_OWORD_FIELD ( temp , FRF_BZ_UDP_WILD_SRCH_LIMIT , 8 ) ;
EFX_SET_OWORD_FIELD ( temp , FRF_BZ_TCP_FULL_SRCH_LIMIT , 8 ) ;
EFX_SET_OWORD_FIELD ( temp , FRF_BZ_TCP_WILD_SRCH_LIMIT , 8 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & temp , FR_BZ_RX_FILTER_CTL ) ;
2008-04-27 12:55:59 +01:00
}
2009-10-23 08:30:36 +00:00
/* XXX This is documented only for Falcon A0/A1 */
2008-04-27 12:55:59 +01:00
/* Setup RX. Wait for descriptor is broken and must
* be disabled . RXDP recovery shouldn ' t be needed , but is .
*/
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & temp , FR_AA_RX_SELF_RST ) ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( temp , FRF_AA_RX_NODESC_WAIT_DIS , 1 ) ;
EFX_SET_OWORD_FIELD ( temp , FRF_AA_RX_SELF_RST_EN , 1 ) ;
2008-04-27 12:55:59 +01:00
if ( EFX_WORKAROUND_5583 ( efx ) )
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( temp , FRF_AA_RX_ISCSI_DIS , 1 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & temp , FR_AA_RX_SELF_RST ) ;
2008-04-27 12:55:59 +01:00
/* Do not enable TX_NO_EOP_DISC_EN, since it limits packets to 16
* descriptors ( which is bad ) .
*/
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & temp , FR_AZ_TX_CFG ) ;
2009-10-23 08:30:36 +00:00
EFX_SET_OWORD_FIELD ( temp , FRF_AZ_TX_NO_EOP_DISC_EN , 0 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & temp , FR_AZ_TX_CFG ) ;
2008-04-27 12:55:59 +01:00
2009-10-23 08:30:06 +00:00
falcon_init_rx_cfg ( efx ) ;
2008-04-27 12:55:59 +01:00
/* Set destination of both TX and RX Flush events */
2009-11-28 05:36:04 +00:00
if ( efx_nic_rev ( efx ) > = EFX_REV_FALCON_B0 ) {
2009-10-23 08:30:36 +00:00
EFX_POPULATE_OWORD_1 ( temp , FRF_BZ_FLS_EVQ_ID , 0 ) ;
2009-10-23 08:30:46 +00:00
efx_writeo ( efx , & temp , FR_BZ_DP_CTRL ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-29 03:43:56 +00:00
efx_nic_init_common ( efx ) ;
2008-04-27 12:55:59 +01:00
return 0 ;
}
2009-11-29 03:42:31 +00:00
static void falcon_remove_nic ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
struct falcon_nic_data * nic_data = efx - > nic_data ;
2009-11-23 16:06:02 +00:00
struct falcon_board * board = falcon_board ( efx ) ;
2008-05-30 22:27:04 +01:00
int rc ;
2009-11-25 16:09:41 +00:00
board - > type - > fini ( efx ) ;
2009-11-23 16:05:12 +00:00
2009-03-04 09:53:02 +00:00
/* Remove I2C adapter and clear it in preparation for a retry */
2009-11-23 16:06:02 +00:00
rc = i2c_del_adapter ( & board - > i2c_adap ) ;
2008-05-30 22:27:04 +01:00
BUG_ON ( rc ) ;
2009-11-23 16:06:02 +00:00
memset ( & board - > i2c_adap , 0 , sizeof ( board - > i2c_adap ) ) ;
2008-04-27 12:55:59 +01:00
2008-09-01 12:47:16 +01:00
falcon_remove_spi_devices ( efx ) ;
2009-11-29 03:43:56 +00:00
efx_nic_free_buffer ( efx , & efx - > irq_status ) ;
2008-04-27 12:55:59 +01:00
2008-05-16 21:14:27 +01:00
falcon_reset_hw ( efx , RESET_TYPE_ALL ) ;
2008-04-27 12:55:59 +01:00
/* Release the second function after the reset */
if ( nic_data - > pci_dev2 ) {
pci_dev_put ( nic_data - > pci_dev2 ) ;
nic_data - > pci_dev2 = NULL ;
}
/* Tear down the private nic state */
kfree ( efx - > nic_data ) ;
efx - > nic_data = NULL ;
}
2009-11-29 03:42:31 +00:00
static void falcon_update_nic_stats ( struct efx_nic * efx )
2008-04-27 12:55:59 +01:00
{
2009-11-25 16:11:35 +00:00
struct falcon_nic_data * nic_data = efx - > nic_data ;
2008-04-27 12:55:59 +01:00
efx_oword_t cnt ;
2009-11-25 16:11:35 +00:00
if ( nic_data - > stats_disable_count )
return ;
2009-10-23 08:30:46 +00:00
efx_reado ( efx , & cnt , FR_AZ_RX_NODESC_DROP ) ;
2009-10-23 08:30:36 +00:00
efx - > n_rx_nodesc_drop_cnt + =
EFX_OWORD_FIELD ( cnt , FRF_AB_RX_NODESC_DROP_CNT ) ;
2009-11-25 16:11:35 +00:00
if ( nic_data - > stats_pending & &
* nic_data - > stats_dma_done = = FALCON_STATS_DONE ) {
nic_data - > stats_pending = false ;
rmb ( ) ; /* read the done flag before the stats */
efx - > mac_op - > update_stats ( efx ) ;
}
}
void falcon_start_nic_stats ( struct efx_nic * efx )
{
struct falcon_nic_data * nic_data = efx - > nic_data ;
spin_lock_bh ( & efx - > stats_lock ) ;
if ( - - nic_data - > stats_disable_count = = 0 )
falcon_stats_request ( efx ) ;
spin_unlock_bh ( & efx - > stats_lock ) ;
}
void falcon_stop_nic_stats ( struct efx_nic * efx )
{
struct falcon_nic_data * nic_data = efx - > nic_data ;
int i ;
might_sleep ( ) ;
spin_lock_bh ( & efx - > stats_lock ) ;
+ + nic_data - > stats_disable_count ;
spin_unlock_bh ( & efx - > stats_lock ) ;
del_timer_sync ( & nic_data - > stats_timer ) ;
/* Wait enough time for the most recent transfer to
* complete . */
for ( i = 0 ; i < 4 & & nic_data - > stats_pending ; i + + ) {
if ( * nic_data - > stats_dma_done = = FALCON_STATS_DONE )
break ;
msleep ( 1 ) ;
}
spin_lock_bh ( & efx - > stats_lock ) ;
falcon_stats_complete ( efx ) ;
spin_unlock_bh ( & efx - > stats_lock ) ;
2008-04-27 12:55:59 +01:00
}
2009-11-29 03:43:43 +00:00
static void falcon_set_id_led ( struct efx_nic * efx , enum efx_led_mode mode )
{
falcon_board ( efx ) - > type - > set_id_led ( efx , mode ) ;
}
2009-11-29 03:43:07 +00:00
/**************************************************************************
*
* Wake on LAN
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static void falcon_get_wol ( struct efx_nic * efx , struct ethtool_wolinfo * wol )
{
wol - > supported = 0 ;
wol - > wolopts = 0 ;
memset ( & wol - > sopass , 0 , sizeof ( wol - > sopass ) ) ;
}
static int falcon_set_wol ( struct efx_nic * efx , u32 type )
{
if ( type ! = 0 )
return - EINVAL ;
return 0 ;
}
2008-04-27 12:55:59 +01:00
/**************************************************************************
*
* Revision - dependent attributes used by efx . c
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2009-11-28 05:36:04 +00:00
struct efx_nic_type falcon_a1_nic_type = {
2009-11-29 03:42:31 +00:00
. probe = falcon_probe_nic ,
. remove = falcon_remove_nic ,
. init = falcon_init_nic ,
. fini = efx_port_dummy_op_void ,
. monitor = falcon_monitor ,
. reset = falcon_reset_hw ,
. probe_port = falcon_probe_port ,
. remove_port = falcon_remove_port ,
. prepare_flush = falcon_prepare_flush ,
. update_stats = falcon_update_nic_stats ,
. start_stats = falcon_start_nic_stats ,
. stop_stats = falcon_stop_nic_stats ,
2009-11-29 03:43:43 +00:00
. set_id_led = falcon_set_id_led ,
2009-11-29 03:42:31 +00:00
. push_irq_moderation = falcon_push_irq_moderation ,
. push_multicast_hash = falcon_push_multicast_hash ,
2009-11-29 03:42:41 +00:00
. reconfigure_port = falcon_reconfigure_port ,
2009-11-29 03:43:07 +00:00
. get_wol = falcon_get_wol ,
. set_wol = falcon_set_wol ,
. resume_wol = efx_port_dummy_op_void ,
2009-11-29 03:43:33 +00:00
. test_nvram = falcon_test_nvram ,
2009-11-28 05:35:00 +00:00
. default_mac_ops = & falcon_xmac_operations ,
2009-11-28 05:36:04 +00:00
. revision = EFX_REV_FALCON_A1 ,
2008-04-27 12:55:59 +01:00
. mem_map_size = 0x20000 ,
2009-10-23 08:30:36 +00:00
. txd_ptr_tbl_base = FR_AA_TX_DESC_PTR_TBL_KER ,
. rxd_ptr_tbl_base = FR_AA_RX_DESC_PTR_TBL_KER ,
. buf_tbl_base = FR_AA_BUF_FULL_TBL_KER ,
. evq_ptr_tbl_base = FR_AA_EVQ_PTR_TBL_KER ,
. evq_rptr_tbl_base = FR_AA_EVQ_RPTR_KER ,
2009-10-23 08:31:07 +00:00
. max_dma_mask = DMA_BIT_MASK ( FSF_AZ_TX_KER_BUF_ADDR_WIDTH ) ,
2008-04-27 12:55:59 +01:00
. rx_buffer_padding = 0x24 ,
. max_interrupt_mode = EFX_INT_MODE_MSI ,
. phys_addr_channels = 4 ,
2009-11-28 05:36:12 +00:00
. tx_dc_base = 0x130000 ,
. rx_dc_base = 0x100000 ,
2009-11-29 15:11:02 +00:00
. offload_features = NETIF_F_IP_CSUM ,
2009-11-29 03:43:15 +00:00
. reset_world_flags = ETH_RESET_IRQ ,
2008-04-27 12:55:59 +01:00
} ;
2009-11-28 05:36:04 +00:00
struct efx_nic_type falcon_b0_nic_type = {
2009-11-29 03:42:31 +00:00
. probe = falcon_probe_nic ,
. remove = falcon_remove_nic ,
. init = falcon_init_nic ,
. fini = efx_port_dummy_op_void ,
. monitor = falcon_monitor ,
. reset = falcon_reset_hw ,
. probe_port = falcon_probe_port ,
. remove_port = falcon_remove_port ,
. prepare_flush = falcon_prepare_flush ,
. update_stats = falcon_update_nic_stats ,
. start_stats = falcon_start_nic_stats ,
. stop_stats = falcon_stop_nic_stats ,
2009-11-29 03:43:43 +00:00
. set_id_led = falcon_set_id_led ,
2009-11-29 03:42:31 +00:00
. push_irq_moderation = falcon_push_irq_moderation ,
. push_multicast_hash = falcon_push_multicast_hash ,
2009-11-29 03:42:41 +00:00
. reconfigure_port = falcon_reconfigure_port ,
2009-11-29 03:43:07 +00:00
. get_wol = falcon_get_wol ,
. set_wol = falcon_set_wol ,
. resume_wol = efx_port_dummy_op_void ,
2009-11-29 03:43:23 +00:00
. test_registers = falcon_b0_test_registers ,
2009-11-29 03:43:33 +00:00
. test_nvram = falcon_test_nvram ,
2009-11-28 05:35:00 +00:00
. default_mac_ops = & falcon_xmac_operations ,
2009-11-28 05:36:04 +00:00
. revision = EFX_REV_FALCON_B0 ,
2008-04-27 12:55:59 +01:00
/* Map everything up to and including the RSS indirection
* table . Don ' t map MSI - X table , MSI - X PBA since Linux
* requires that they not be mapped . */
2009-10-23 08:30:36 +00:00
. mem_map_size = ( FR_BZ_RX_INDIRECTION_TBL +
FR_BZ_RX_INDIRECTION_TBL_STEP *
FR_BZ_RX_INDIRECTION_TBL_ROWS ) ,
. txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL ,
. rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL ,
. buf_tbl_base = FR_BZ_BUF_FULL_TBL ,
. evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL ,
. evq_rptr_tbl_base = FR_BZ_EVQ_RPTR ,
2009-10-23 08:31:07 +00:00
. max_dma_mask = DMA_BIT_MASK ( FSF_AZ_TX_KER_BUF_ADDR_WIDTH ) ,
2008-04-27 12:55:59 +01:00
. rx_buffer_padding = 0 ,
. max_interrupt_mode = EFX_INT_MODE_MSIX ,
. phys_addr_channels = 32 , /* Hardware limit is 64, but the legacy
* interrupt handler only supports 32
* channels */
2009-11-28 05:36:12 +00:00
. tx_dc_base = 0x130000 ,
. rx_dc_base = 0x100000 ,
2009-11-29 15:11:02 +00:00
. offload_features = NETIF_F_IP_CSUM ,
2009-11-29 03:43:15 +00:00
. reset_world_flags = ETH_RESET_IRQ ,
2008-04-27 12:55:59 +01:00
} ;