2005-04-16 15:20:36 -07:00
/*******************************************************************************
2006-09-27 12:53:14 -07:00
Intel PRO / 1000 Linux driver
Copyright ( c ) 1999 - 2006 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
2005-04-16 15:20:36 -07:00
more details .
2006-09-27 12:53:14 -07:00
2005-04-16 15:20:36 -07:00
You should have received a copy of the GNU General Public License along with
2006-09-27 12:53:14 -07:00
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 " .
2005-04-16 15:20:36 -07:00
Contact Information :
Linux NICS < linux . nics @ intel . com >
2006-04-14 19:05:31 -07:00
e1000 - devel Mailing List < e1000 - devel @ lists . sourceforge . net >
2005-04-16 15:20:36 -07:00
Intel Corporation , 5200 N . E . Elam Young Parkway , Hillsboro , OR 97124 - 6497
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* ethtool support for e1000 */
# include "e1000.h"
# include <asm/uaccess.h>
2009-10-13 01:45:48 +00:00
enum { NETDEV_STATS , E1000_STATS } ;
2005-04-16 15:20:36 -07:00
struct e1000_stats {
char stat_string [ ETH_GSTRING_LEN ] ;
2009-10-13 01:45:48 +00:00
int type ;
2005-04-16 15:20:36 -07:00
int sizeof_stat ;
int stat_offset ;
} ;
2009-10-13 01:45:48 +00:00
# define E1000_STAT(m) E1000_STATS, \
sizeof ( ( ( struct e1000_adapter * ) 0 ) - > m ) , \
offsetof ( struct e1000_adapter , m )
# define E1000_NETDEV_STAT(m) NETDEV_STATS, \
sizeof ( ( ( struct net_device * ) 0 ) - > m ) , \
offsetof ( struct net_device , m )
2005-04-16 15:20:36 -07:00
static const struct e1000_stats e1000_gstrings_stats [ ] = {
2006-09-27 12:53:37 -07:00
{ " rx_packets " , E1000_STAT ( stats . gprc ) } ,
{ " tx_packets " , E1000_STAT ( stats . gptc ) } ,
{ " rx_bytes " , E1000_STAT ( stats . gorcl ) } ,
{ " tx_bytes " , E1000_STAT ( stats . gotcl ) } ,
{ " rx_broadcast " , E1000_STAT ( stats . bprc ) } ,
{ " tx_broadcast " , E1000_STAT ( stats . bptc ) } ,
{ " rx_multicast " , E1000_STAT ( stats . mprc ) } ,
{ " tx_multicast " , E1000_STAT ( stats . mptc ) } ,
{ " rx_errors " , E1000_STAT ( stats . rxerrc ) } ,
{ " tx_errors " , E1000_STAT ( stats . txerrc ) } ,
2009-10-07 02:42:23 +00:00
{ " tx_dropped " , E1000_NETDEV_STAT ( stats . tx_dropped ) } ,
2006-09-27 12:53:37 -07:00
{ " multicast " , E1000_STAT ( stats . mprc ) } ,
{ " collisions " , E1000_STAT ( stats . colc ) } ,
{ " rx_length_errors " , E1000_STAT ( stats . rlerrc ) } ,
2009-10-07 02:42:23 +00:00
{ " rx_over_errors " , E1000_NETDEV_STAT ( stats . rx_over_errors ) } ,
2006-09-27 12:53:37 -07:00
{ " rx_crc_errors " , E1000_STAT ( stats . crcerrs ) } ,
2009-10-07 02:42:23 +00:00
{ " rx_frame_errors " , E1000_NETDEV_STAT ( stats . rx_frame_errors ) } ,
2005-04-28 19:44:46 -07:00
{ " rx_no_buffer_count " , E1000_STAT ( stats . rnbc ) } ,
2006-09-27 12:53:37 -07:00
{ " rx_missed_errors " , E1000_STAT ( stats . mpc ) } ,
{ " tx_aborted_errors " , E1000_STAT ( stats . ecol ) } ,
{ " tx_carrier_errors " , E1000_STAT ( stats . tncrs ) } ,
2009-10-07 02:42:23 +00:00
{ " tx_fifo_errors " , E1000_NETDEV_STAT ( stats . tx_fifo_errors ) } ,
{ " tx_heartbeat_errors " , E1000_NETDEV_STAT ( stats . tx_heartbeat_errors ) } ,
2006-09-27 12:53:37 -07:00
{ " tx_window_errors " , E1000_STAT ( stats . latecol ) } ,
2005-04-16 15:20:36 -07:00
{ " tx_abort_late_coll " , E1000_STAT ( stats . latecol ) } ,
{ " tx_deferred_ok " , E1000_STAT ( stats . dc ) } ,
{ " tx_single_coll_ok " , E1000_STAT ( stats . scc ) } ,
{ " tx_multi_coll_ok " , E1000_STAT ( stats . mcc ) } ,
2006-01-12 16:50:35 -08:00
{ " tx_timeout_count " , E1000_STAT ( tx_timeout_count ) } ,
2006-11-01 08:47:59 -08:00
{ " tx_restart_queue " , E1000_STAT ( restart_queue ) } ,
2005-04-16 15:20:36 -07:00
{ " rx_long_length_errors " , E1000_STAT ( stats . roc ) } ,
{ " rx_short_length_errors " , E1000_STAT ( stats . ruc ) } ,
{ " rx_align_errors " , E1000_STAT ( stats . algnerrc ) } ,
{ " tx_tcp_seg_good " , E1000_STAT ( stats . tsctc ) } ,
{ " tx_tcp_seg_failed " , E1000_STAT ( stats . tsctfc ) } ,
{ " rx_flow_control_xon " , E1000_STAT ( stats . xonrxc ) } ,
{ " rx_flow_control_xoff " , E1000_STAT ( stats . xoffrxc ) } ,
{ " tx_flow_control_xon " , E1000_STAT ( stats . xontxc ) } ,
{ " tx_flow_control_xoff " , E1000_STAT ( stats . xofftxc ) } ,
{ " rx_long_byte_count " , E1000_STAT ( stats . gorcl ) } ,
{ " rx_csum_offload_good " , E1000_STAT ( hw_csum_good ) } ,
2005-10-04 07:05:44 -04:00
{ " rx_csum_offload_errors " , E1000_STAT ( hw_csum_err ) } ,
2006-01-12 16:50:35 -08:00
{ " alloc_rx_buff_failed " , E1000_STAT ( alloc_rx_buff_failed ) } ,
2006-12-15 11:16:33 -05:00
{ " tx_smbus " , E1000_STAT ( stats . mgptc ) } ,
{ " rx_smbus " , E1000_STAT ( stats . mgprc ) } ,
{ " dropped_smbus " , E1000_STAT ( stats . mgpdc ) } ,
2005-04-16 15:20:36 -07:00
} ;
2006-01-12 16:50:41 -08:00
# define E1000_QUEUE_STATS_LEN 0
2007-09-02 18:30:18 +08:00
# define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
2006-01-12 16:50:41 -08:00
# define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)
2005-04-16 15:20:36 -07:00
static const char e1000_gstrings_test [ ] [ ETH_GSTRING_LEN ] = {
" Register test (offline) " , " Eeprom test (offline) " ,
" Interrupt test (offline) " , " Loopback test (offline) " ,
" Link test (on/offline) "
} ;
2007-10-18 10:00:15 +02:00
# define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:02 -07:00
static int e1000_get_settings ( struct net_device * netdev ,
struct ethtool_cmd * ecmd )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2006-01-18 13:01:39 -08:00
if ( hw - > media_type = = e1000_media_type_copper ) {
2005-04-16 15:20:36 -07:00
ecmd - > supported = ( SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP ) ;
ecmd - > advertising = ADVERTISED_TP ;
2006-01-18 13:01:39 -08:00
if ( hw - > autoneg = = 1 ) {
2005-04-16 15:20:36 -07:00
ecmd - > advertising | = ADVERTISED_Autoneg ;
/* the e1000 autoneg seems to match ethtool nicely */
ecmd - > advertising | = hw - > autoneg_advertised ;
}
ecmd - > port = PORT_TP ;
ecmd - > phy_address = hw - > phy_addr ;
2006-01-18 13:01:39 -08:00
if ( hw - > mac_type = = e1000_82543 )
2005-04-16 15:20:36 -07:00
ecmd - > transceiver = XCVR_EXTERNAL ;
else
ecmd - > transceiver = XCVR_INTERNAL ;
} else {
ecmd - > supported = ( SUPPORTED_1000baseT_Full |
SUPPORTED_FIBRE |
SUPPORTED_Autoneg ) ;
2005-06-17 17:43:06 -07:00
ecmd - > advertising = ( ADVERTISED_1000baseT_Full |
ADVERTISED_FIBRE |
ADVERTISED_Autoneg ) ;
2005-04-16 15:20:36 -07:00
ecmd - > port = PORT_FIBRE ;
2006-01-18 13:01:39 -08:00
if ( hw - > mac_type > = e1000_82545 )
2005-04-16 15:20:36 -07:00
ecmd - > transceiver = XCVR_INTERNAL ;
else
ecmd - > transceiver = XCVR_EXTERNAL ;
}
2008-07-11 15:17:08 -07:00
if ( er32 ( STATUS ) & E1000_STATUS_LU ) {
2005-04-16 15:20:36 -07:00
e1000_get_speed_and_duplex ( hw , & adapter - > link_speed ,
& adapter - > link_duplex ) ;
ecmd - > speed = adapter - > link_speed ;
/* unfortunatly FULL_DUPLEX != DUPLEX_FULL
* and HALF_DUPLEX ! = DUPLEX_HALF */
2006-01-18 13:01:39 -08:00
if ( adapter - > link_duplex = = FULL_DUPLEX )
2005-04-16 15:20:36 -07:00
ecmd - > duplex = DUPLEX_FULL ;
else
ecmd - > duplex = DUPLEX_HALF ;
} else {
ecmd - > speed = - 1 ;
ecmd - > duplex = - 1 ;
}
ecmd - > autoneg = ( ( hw - > media_type = = e1000_media_type_fiber ) | |
hw - > autoneg ) ? AUTONEG_ENABLE : AUTONEG_DISABLE ;
return 0 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_set_settings ( struct net_device * netdev ,
struct ethtool_cmd * ecmd )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2006-08-16 13:38:46 -07:00
while ( test_and_set_bit ( __E1000_RESETTING , & adapter - > flags ) )
msleep ( 1 ) ;
2006-01-12 16:50:28 -08:00
if ( ecmd - > autoneg = = AUTONEG_ENABLE ) {
2005-04-16 15:20:36 -07:00
hw - > autoneg = 1 ;
2006-01-18 13:01:39 -08:00
if ( hw - > media_type = = e1000_media_type_fiber )
2005-06-17 17:43:06 -07:00
hw - > autoneg_advertised = ADVERTISED_1000baseT_Full |
ADVERTISED_FIBRE |
ADVERTISED_Autoneg ;
2006-01-18 13:01:39 -08:00
else
2006-09-27 12:53:40 -07:00
hw - > autoneg_advertised = ecmd - > advertising |
ADVERTISED_TP |
ADVERTISED_Autoneg ;
2005-06-17 17:43:06 -07:00
ecmd - > advertising = hw - > autoneg_advertised ;
2005-04-16 15:20:36 -07:00
} else
2006-08-16 13:38:46 -07:00
if ( e1000_set_spd_dplx ( adapter , ecmd - > speed + ecmd - > duplex ) ) {
clear_bit ( __E1000_RESETTING , & adapter - > flags ) ;
2005-04-16 15:20:36 -07:00
return - EINVAL ;
2006-08-16 13:38:46 -07:00
}
2005-04-16 15:20:36 -07:00
/* reset the link */
2006-08-16 13:38:46 -07:00
if ( netif_running ( adapter - > netdev ) ) {
e1000_down ( adapter ) ;
e1000_up ( adapter ) ;
} else
2005-04-16 15:20:36 -07:00
e1000_reset ( adapter ) ;
2006-08-16 13:38:46 -07:00
clear_bit ( __E1000_RESETTING , & adapter - > flags ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2010-02-03 14:49:28 +00:00
static u32 e1000_get_link ( struct net_device * netdev )
{
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
/*
* If the link is not reported up to netdev , interrupts are disabled ,
* and so the physical link state may have changed since we last
* looked . Set get_link_status to make sure that the true link
* state is interrogated , rather than pulling a cached and possibly
* stale link state from the driver .
*/
if ( ! netif_carrier_ok ( netdev ) )
adapter - > hw . get_link_status = 1 ;
return e1000_has_link ( adapter ) ;
}
2008-07-11 15:17:02 -07:00
static void e1000_get_pauseparam ( struct net_device * netdev ,
struct ethtool_pauseparam * pause )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2006-01-18 13:01:39 -08:00
pause - > autoneg =
2005-04-16 15:20:36 -07:00
( adapter - > fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE ) ;
2006-01-18 13:01:39 -08:00
2006-09-27 12:53:28 -07:00
if ( hw - > fc = = E1000_FC_RX_PAUSE )
2005-04-16 15:20:36 -07:00
pause - > rx_pause = 1 ;
2006-09-27 12:53:28 -07:00
else if ( hw - > fc = = E1000_FC_TX_PAUSE )
2005-04-16 15:20:36 -07:00
pause - > tx_pause = 1 ;
2006-09-27 12:53:28 -07:00
else if ( hw - > fc = = E1000_FC_FULL ) {
2005-04-16 15:20:36 -07:00
pause - > rx_pause = 1 ;
pause - > tx_pause = 1 ;
}
}
2008-07-11 15:17:02 -07:00
static int e1000_set_pauseparam ( struct net_device * netdev ,
struct ethtool_pauseparam * pause )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2006-08-16 13:38:46 -07:00
int retval = 0 ;
2006-01-18 13:01:39 -08:00
2005-04-16 15:20:36 -07:00
adapter - > fc_autoneg = pause - > autoneg ;
2006-08-16 13:38:46 -07:00
while ( test_and_set_bit ( __E1000_RESETTING , & adapter - > flags ) )
msleep ( 1 ) ;
2006-01-18 13:01:39 -08:00
if ( pause - > rx_pause & & pause - > tx_pause )
2006-09-27 12:53:28 -07:00
hw - > fc = E1000_FC_FULL ;
2006-01-18 13:01:39 -08:00
else if ( pause - > rx_pause & & ! pause - > tx_pause )
2006-09-27 12:53:28 -07:00
hw - > fc = E1000_FC_RX_PAUSE ;
2006-01-18 13:01:39 -08:00
else if ( ! pause - > rx_pause & & pause - > tx_pause )
2006-09-27 12:53:28 -07:00
hw - > fc = E1000_FC_TX_PAUSE ;
2006-01-18 13:01:39 -08:00
else if ( ! pause - > rx_pause & & ! pause - > tx_pause )
2006-09-27 12:53:28 -07:00
hw - > fc = E1000_FC_NONE ;
2005-04-16 15:20:36 -07:00
hw - > original_fc = hw - > fc ;
2006-01-18 13:01:39 -08:00
if ( adapter - > fc_autoneg = = AUTONEG_ENABLE ) {
2006-08-16 13:38:46 -07:00
if ( netif_running ( adapter - > netdev ) ) {
e1000_down ( adapter ) ;
e1000_up ( adapter ) ;
} else
2005-04-16 15:20:36 -07:00
e1000_reset ( adapter ) ;
2006-01-18 13:01:39 -08:00
} else
2006-08-16 13:38:46 -07:00
retval = ( ( hw - > media_type = = e1000_media_type_fiber ) ?
2006-11-01 08:47:30 -08:00
e1000_setup_link ( hw ) : e1000_force_mac_fc ( hw ) ) ;
2006-01-18 13:01:39 -08:00
2006-08-16 13:38:46 -07:00
clear_bit ( __E1000_RESETTING , & adapter - > flags ) ;
return retval ;
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static u32 e1000_get_rx_csum ( struct net_device * netdev )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
return adapter - > rx_csum ;
}
2008-07-11 15:17:02 -07:00
static int e1000_set_rx_csum ( struct net_device * netdev , u32 data )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
adapter - > rx_csum = data ;
2006-06-27 09:06:28 -07:00
if ( netif_running ( netdev ) )
e1000_reinit_locked ( adapter ) ;
else
2005-04-16 15:20:36 -07:00
e1000_reset ( adapter ) ;
return 0 ;
}
2006-01-18 13:01:39 -08:00
2008-07-11 15:17:02 -07:00
static u32 e1000_get_tx_csum ( struct net_device * netdev )
2005-04-16 15:20:36 -07:00
{
return ( netdev - > features & NETIF_F_HW_CSUM ) ! = 0 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_set_tx_csum ( struct net_device * netdev , u32 data )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
if ( hw - > mac_type < e1000_82543 ) {
2005-04-16 15:20:36 -07:00
if ( ! data )
return - EINVAL ;
return 0 ;
}
if ( data )
netdev - > features | = NETIF_F_HW_CSUM ;
else
netdev - > features & = ~ NETIF_F_HW_CSUM ;
return 0 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_set_tso ( struct net_device * netdev , u32 data )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
if ( ( hw - > mac_type < e1000_82544 ) | |
( hw - > mac_type = = e1000_82547 ) )
2005-04-16 15:20:36 -07:00
return data ? - EINVAL : 0 ;
if ( data )
netdev - > features | = NETIF_F_TSO ;
else
netdev - > features & = ~ NETIF_F_TSO ;
2006-03-02 18:19:30 -08:00
2009-09-25 12:16:14 +00:00
netdev - > features & = ~ NETIF_F_TSO6 ;
2006-11-01 08:47:36 -08:00
2010-07-26 23:37:21 -07:00
e_info ( probe , " TSO is %s \n " , data ? " Enabled " : " Disabled " ) ;
2008-03-21 11:06:25 -07:00
adapter - > tso_force = true ;
2005-04-16 15:20:36 -07:00
return 0 ;
2006-01-18 13:01:39 -08:00
}
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:02 -07:00
static u32 e1000_get_msglevel ( struct net_device * netdev )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
return adapter - > msg_enable ;
}
2008-07-11 15:17:02 -07:00
static void e1000_set_msglevel ( struct net_device * netdev , u32 data )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
adapter - > msg_enable = data ;
}
2008-07-11 15:17:02 -07:00
static int e1000_get_regs_len ( struct net_device * netdev )
2005-04-16 15:20:36 -07:00
{
# define E1000_REGS_LEN 32
2008-04-03 10:06:32 -07:00
return E1000_REGS_LEN * sizeof ( u32 ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static void e1000_get_regs ( struct net_device * netdev , struct ethtool_regs * regs ,
void * p )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u32 * regs_buff = p ;
u16 phy_data ;
2005-04-16 15:20:36 -07:00
2008-04-03 10:06:32 -07:00
memset ( p , 0 , E1000_REGS_LEN * sizeof ( u32 ) ) ;
2005-04-16 15:20:36 -07:00
regs - > version = ( 1 < < 24 ) | ( hw - > revision_id < < 16 ) | hw - > device_id ;
2008-07-11 15:17:08 -07:00
regs_buff [ 0 ] = er32 ( CTRL ) ;
regs_buff [ 1 ] = er32 ( STATUS ) ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
regs_buff [ 2 ] = er32 ( RCTL ) ;
regs_buff [ 3 ] = er32 ( RDLEN ) ;
regs_buff [ 4 ] = er32 ( RDH ) ;
regs_buff [ 5 ] = er32 ( RDT ) ;
regs_buff [ 6 ] = er32 ( RDTR ) ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
regs_buff [ 7 ] = er32 ( TCTL ) ;
regs_buff [ 8 ] = er32 ( TDLEN ) ;
regs_buff [ 9 ] = er32 ( TDH ) ;
regs_buff [ 10 ] = er32 ( TDT ) ;
regs_buff [ 11 ] = er32 ( TIDV ) ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
regs_buff [ 12 ] = hw - > phy_type ; /* PHY type (IGP=1, M88=0) */
2006-01-18 13:01:39 -08:00
if ( hw - > phy_type = = e1000_phy_igp ) {
2005-04-16 15:20:36 -07:00
e1000_write_phy_reg ( hw , IGP01E1000_PHY_PAGE_SELECT ,
IGP01E1000_PHY_AGC_A ) ;
e1000_read_phy_reg ( hw , IGP01E1000_PHY_AGC_A &
IGP01E1000_PHY_PAGE_SELECT , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 13 ] = ( u32 ) phy_data ; /* cable length */
2005-04-16 15:20:36 -07:00
e1000_write_phy_reg ( hw , IGP01E1000_PHY_PAGE_SELECT ,
IGP01E1000_PHY_AGC_B ) ;
e1000_read_phy_reg ( hw , IGP01E1000_PHY_AGC_B &
IGP01E1000_PHY_PAGE_SELECT , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 14 ] = ( u32 ) phy_data ; /* cable length */
2005-04-16 15:20:36 -07:00
e1000_write_phy_reg ( hw , IGP01E1000_PHY_PAGE_SELECT ,
IGP01E1000_PHY_AGC_C ) ;
e1000_read_phy_reg ( hw , IGP01E1000_PHY_AGC_C &
IGP01E1000_PHY_PAGE_SELECT , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 15 ] = ( u32 ) phy_data ; /* cable length */
2005-04-16 15:20:36 -07:00
e1000_write_phy_reg ( hw , IGP01E1000_PHY_PAGE_SELECT ,
IGP01E1000_PHY_AGC_D ) ;
e1000_read_phy_reg ( hw , IGP01E1000_PHY_AGC_D &
IGP01E1000_PHY_PAGE_SELECT , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 16 ] = ( u32 ) phy_data ; /* cable length */
2005-04-16 15:20:36 -07:00
regs_buff [ 17 ] = 0 ; /* extended 10bt distance (not needed) */
e1000_write_phy_reg ( hw , IGP01E1000_PHY_PAGE_SELECT , 0x0 ) ;
e1000_read_phy_reg ( hw , IGP01E1000_PHY_PORT_STATUS &
IGP01E1000_PHY_PAGE_SELECT , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 18 ] = ( u32 ) phy_data ; /* cable polarity */
2005-04-16 15:20:36 -07:00
e1000_write_phy_reg ( hw , IGP01E1000_PHY_PAGE_SELECT ,
IGP01E1000_PHY_PCS_INIT_REG ) ;
e1000_read_phy_reg ( hw , IGP01E1000_PHY_PCS_INIT_REG &
IGP01E1000_PHY_PAGE_SELECT , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 19 ] = ( u32 ) phy_data ; /* cable polarity */
2005-04-16 15:20:36 -07:00
regs_buff [ 20 ] = 0 ; /* polarity correction enabled (always) */
regs_buff [ 22 ] = 0 ; /* phy receive errors (unavailable) */
regs_buff [ 23 ] = regs_buff [ 18 ] ; /* mdix mode */
e1000_write_phy_reg ( hw , IGP01E1000_PHY_PAGE_SELECT , 0x0 ) ;
} else {
2006-08-28 14:56:16 -07:00
e1000_read_phy_reg ( hw , M88E1000_PHY_SPEC_STATUS , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 13 ] = ( u32 ) phy_data ; /* cable length */
2005-04-16 15:20:36 -07:00
regs_buff [ 14 ] = 0 ; /* Dummy (to align w/ IGP phy reg dump) */
regs_buff [ 15 ] = 0 ; /* Dummy (to align w/ IGP phy reg dump) */
regs_buff [ 16 ] = 0 ; /* Dummy (to align w/ IGP phy reg dump) */
2006-08-28 14:56:16 -07:00
e1000_read_phy_reg ( hw , M88E1000_PHY_SPEC_CTRL , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 17 ] = ( u32 ) phy_data ; /* extended 10bt distance */
2005-04-16 15:20:36 -07:00
regs_buff [ 18 ] = regs_buff [ 13 ] ; /* cable polarity */
regs_buff [ 19 ] = 0 ; /* Dummy (to align w/ IGP phy reg dump) */
regs_buff [ 20 ] = regs_buff [ 17 ] ; /* polarity correction */
/* phy receive errors */
regs_buff [ 22 ] = adapter - > phy_stats . receive_errors ;
regs_buff [ 23 ] = regs_buff [ 13 ] ; /* mdix mode */
}
regs_buff [ 21 ] = adapter - > phy_stats . idle_errors ; /* phy idle errors */
e1000_read_phy_reg ( hw , PHY_1000T_STATUS , & phy_data ) ;
2008-04-03 10:06:32 -07:00
regs_buff [ 24 ] = ( u32 ) phy_data ; /* phy local receiver status */
2005-04-16 15:20:36 -07:00
regs_buff [ 25 ] = regs_buff [ 24 ] ; /* phy remote receiver status */
2006-01-18 13:01:39 -08:00
if ( hw - > mac_type > = e1000_82540 & &
2006-10-24 14:45:53 -07:00
hw - > media_type = = e1000_media_type_copper ) {
2008-07-11 15:17:08 -07:00
regs_buff [ 26 ] = er32 ( MANC ) ;
2005-04-16 15:20:36 -07:00
}
}
2008-07-11 15:17:02 -07:00
static int e1000_get_eeprom_len ( struct net_device * netdev )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
return hw - > eeprom . word_size * 2 ;
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static int e1000_get_eeprom ( struct net_device * netdev ,
struct ethtool_eeprom * eeprom , u8 * bytes )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u16 * eeprom_buff ;
2005-04-16 15:20:36 -07:00
int first_word , last_word ;
int ret_val = 0 ;
2008-04-03 10:06:32 -07:00
u16 i ;
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
if ( eeprom - > len = = 0 )
2005-04-16 15:20:36 -07:00
return - EINVAL ;
eeprom - > magic = hw - > vendor_id | ( hw - > device_id < < 16 ) ;
first_word = eeprom - > offset > > 1 ;
last_word = ( eeprom - > offset + eeprom - > len - 1 ) > > 1 ;
2008-04-03 10:06:32 -07:00
eeprom_buff = kmalloc ( sizeof ( u16 ) *
2005-04-16 15:20:36 -07:00
( last_word - first_word + 1 ) , GFP_KERNEL ) ;
2006-01-18 13:01:39 -08:00
if ( ! eeprom_buff )
2005-04-16 15:20:36 -07:00
return - ENOMEM ;
2006-01-18 13:01:39 -08:00
if ( hw - > eeprom . type = = e1000_eeprom_spi )
2005-04-16 15:20:36 -07:00
ret_val = e1000_read_eeprom ( hw , first_word ,
last_word - first_word + 1 ,
eeprom_buff ) ;
else {
2008-07-11 15:17:28 -07:00
for ( i = 0 ; i < last_word - first_word + 1 ; i + + ) {
ret_val = e1000_read_eeprom ( hw , first_word + i , 1 ,
& eeprom_buff [ i ] ) ;
if ( ret_val )
2005-04-16 15:20:36 -07:00
break ;
2008-07-11 15:17:28 -07:00
}
2005-04-16 15:20:36 -07:00
}
/* Device's eeprom is always little-endian, word addressable */
for ( i = 0 ; i < last_word - first_word + 1 ; i + + )
le16_to_cpus ( & eeprom_buff [ i ] ) ;
2008-04-03 10:06:32 -07:00
memcpy ( bytes , ( u8 * ) eeprom_buff + ( eeprom - > offset & 1 ) ,
2005-04-16 15:20:36 -07:00
eeprom - > len ) ;
kfree ( eeprom_buff ) ;
return ret_val ;
}
2008-07-11 15:17:02 -07:00
static int e1000_set_eeprom ( struct net_device * netdev ,
struct ethtool_eeprom * eeprom , u8 * bytes )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u16 * eeprom_buff ;
2005-04-16 15:20:36 -07:00
void * ptr ;
int max_len , first_word , last_word , ret_val = 0 ;
2008-04-03 10:06:32 -07:00
u16 i ;
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
if ( eeprom - > len = = 0 )
2005-04-16 15:20:36 -07:00
return - EOPNOTSUPP ;
2006-01-18 13:01:39 -08:00
if ( eeprom - > magic ! = ( hw - > vendor_id | ( hw - > device_id < < 16 ) ) )
2005-04-16 15:20:36 -07:00
return - EFAULT ;
max_len = hw - > eeprom . word_size * 2 ;
first_word = eeprom - > offset > > 1 ;
last_word = ( eeprom - > offset + eeprom - > len - 1 ) > > 1 ;
eeprom_buff = kmalloc ( max_len , GFP_KERNEL ) ;
2006-01-18 13:01:39 -08:00
if ( ! eeprom_buff )
2005-04-16 15:20:36 -07:00
return - ENOMEM ;
ptr = ( void * ) eeprom_buff ;
2006-01-18 13:01:39 -08:00
if ( eeprom - > offset & 1 ) {
2005-04-16 15:20:36 -07:00
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
ret_val = e1000_read_eeprom ( hw , first_word , 1 ,
& eeprom_buff [ 0 ] ) ;
ptr + + ;
}
2006-01-18 13:01:39 -08:00
if ( ( ( eeprom - > offset + eeprom - > len ) & 1 ) & & ( ret_val = = 0 ) ) {
2005-04-16 15:20:36 -07:00
/* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */
ret_val = e1000_read_eeprom ( hw , last_word , 1 ,
& eeprom_buff [ last_word - first_word ] ) ;
}
/* Device's eeprom is always little-endian, word addressable */
for ( i = 0 ; i < last_word - first_word + 1 ; i + + )
le16_to_cpus ( & eeprom_buff [ i ] ) ;
memcpy ( ptr , bytes , eeprom - > len ) ;
for ( i = 0 ; i < last_word - first_word + 1 ; i + + )
eeprom_buff [ i ] = cpu_to_le16 ( eeprom_buff [ i ] ) ;
ret_val = e1000_write_eeprom ( hw , first_word ,
last_word - first_word + 1 , eeprom_buff ) ;
2009-09-25 12:16:14 +00:00
/* Update the checksum over the first part of the EEPROM if needed */
if ( ( ret_val = = 0 ) & & ( first_word < = EEPROM_CHECKSUM_REG ) )
2005-04-16 15:20:36 -07:00
e1000_update_eeprom_checksum ( hw ) ;
kfree ( eeprom_buff ) ;
return ret_val ;
}
2008-07-11 15:17:02 -07:00
static void e1000_get_drvinfo ( struct net_device * netdev ,
struct ethtool_drvinfo * drvinfo )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2006-01-12 16:51:23 -08:00
char firmware_version [ 32 ] ;
2005-04-16 15:20:36 -07:00
strncpy ( drvinfo - > driver , e1000_driver_name , 32 ) ;
strncpy ( drvinfo - > version , e1000_driver_version , 32 ) ;
2006-01-12 16:51:23 -08:00
2009-09-25 12:16:14 +00:00
sprintf ( firmware_version , " N/A " ) ;
2006-01-12 16:51:23 -08:00
strncpy ( drvinfo - > fw_version , firmware_version , 32 ) ;
2005-04-16 15:20:36 -07:00
strncpy ( drvinfo - > bus_info , pci_name ( adapter - > pdev ) , 32 ) ;
drvinfo - > regdump_len = e1000_get_regs_len ( netdev ) ;
drvinfo - > eedump_len = e1000_get_eeprom_len ( netdev ) ;
}
2008-07-11 15:17:02 -07:00
static void e1000_get_ringparam ( struct net_device * netdev ,
struct ethtool_ringparam * ring )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
e1000_mac_type mac_type = hw - > mac_type ;
2005-10-04 07:01:55 -04:00
struct e1000_tx_ring * txdr = adapter - > tx_ring ;
struct e1000_rx_ring * rxdr = adapter - > rx_ring ;
2005-04-16 15:20:36 -07:00
ring - > rx_max_pending = ( mac_type < e1000_82544 ) ? E1000_MAX_RXD :
E1000_MAX_82544_RXD ;
ring - > tx_max_pending = ( mac_type < e1000_82544 ) ? E1000_MAX_TXD :
E1000_MAX_82544_TXD ;
ring - > rx_mini_max_pending = 0 ;
ring - > rx_jumbo_max_pending = 0 ;
ring - > rx_pending = rxdr - > count ;
ring - > tx_pending = txdr - > count ;
ring - > rx_mini_pending = 0 ;
ring - > rx_jumbo_pending = 0 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_set_ringparam ( struct net_device * netdev ,
struct ethtool_ringparam * ring )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
e1000_mac_type mac_type = hw - > mac_type ;
2006-09-27 12:54:14 -07:00
struct e1000_tx_ring * txdr , * tx_old ;
struct e1000_rx_ring * rxdr , * rx_old ;
2007-03-06 08:58:04 -08:00
int i , err ;
2005-10-04 07:01:55 -04:00
2006-03-02 18:17:16 -08:00
if ( ( ring - > rx_mini_pending ) | | ( ring - > rx_jumbo_pending ) )
return - EINVAL ;
2006-06-27 09:06:28 -07:00
while ( test_and_set_bit ( __E1000_RESETTING , & adapter - > flags ) )
msleep ( 1 ) ;
2005-10-04 07:01:55 -04:00
if ( netif_running ( adapter - > netdev ) )
e1000_down ( adapter ) ;
2005-04-16 15:20:36 -07:00
tx_old = adapter - > tx_ring ;
rx_old = adapter - > rx_ring ;
2006-09-27 12:54:14 -07:00
err = - ENOMEM ;
2007-03-06 08:58:04 -08:00
txdr = kcalloc ( adapter - > num_tx_queues , sizeof ( struct e1000_tx_ring ) , GFP_KERNEL ) ;
2006-09-27 12:54:14 -07:00
if ( ! txdr )
goto err_alloc_tx ;
2005-10-04 07:01:55 -04:00
2007-03-06 08:58:04 -08:00
rxdr = kcalloc ( adapter - > num_rx_queues , sizeof ( struct e1000_rx_ring ) , GFP_KERNEL ) ;
2006-09-27 12:54:14 -07:00
if ( ! rxdr )
goto err_alloc_rx ;
2005-10-04 07:01:55 -04:00
2006-09-27 12:54:14 -07:00
adapter - > tx_ring = txdr ;
adapter - > rx_ring = rxdr ;
2005-10-04 07:01:55 -04:00
2008-04-03 10:06:32 -07:00
rxdr - > count = max ( ring - > rx_pending , ( u32 ) E1000_MIN_RXD ) ;
rxdr - > count = min ( rxdr - > count , ( u32 ) ( mac_type < e1000_82544 ?
2005-04-16 15:20:36 -07:00
E1000_MAX_RXD : E1000_MAX_82544_RXD ) ) ;
2007-04-27 13:55:29 -07:00
rxdr - > count = ALIGN ( rxdr - > count , REQ_RX_DESCRIPTOR_MULTIPLE ) ;
2005-04-16 15:20:36 -07:00
2008-04-03 10:06:32 -07:00
txdr - > count = max ( ring - > tx_pending , ( u32 ) E1000_MIN_TXD ) ;
txdr - > count = min ( txdr - > count , ( u32 ) ( mac_type < e1000_82544 ?
2005-04-16 15:20:36 -07:00
E1000_MAX_TXD : E1000_MAX_82544_TXD ) ) ;
2007-04-27 13:55:29 -07:00
txdr - > count = ALIGN ( txdr - > count , REQ_TX_DESCRIPTOR_MULTIPLE ) ;
2005-04-16 15:20:36 -07:00
2006-01-12 16:50:39 -08:00
for ( i = 0 ; i < adapter - > num_tx_queues ; i + + )
2005-10-04 07:01:55 -04:00
txdr [ i ] . count = txdr - > count ;
2006-01-12 16:50:39 -08:00
for ( i = 0 ; i < adapter - > num_rx_queues ; i + + )
2005-10-04 07:01:55 -04:00
rxdr [ i ] . count = rxdr - > count ;
2006-01-18 13:01:39 -08:00
if ( netif_running ( adapter - > netdev ) ) {
2005-04-16 15:20:36 -07:00
/* Try to get new resources before deleting old */
2008-07-11 15:17:28 -07:00
err = e1000_setup_all_rx_resources ( adapter ) ;
if ( err )
2005-04-16 15:20:36 -07:00
goto err_setup_rx ;
2008-07-11 15:17:28 -07:00
err = e1000_setup_all_tx_resources ( adapter ) ;
if ( err )
2005-04-16 15:20:36 -07:00
goto err_setup_tx ;
/* save the new, restore the old in order to free it,
* then restore the new back again */
adapter - > rx_ring = rx_old ;
adapter - > tx_ring = tx_old ;
2005-10-04 07:01:55 -04:00
e1000_free_all_rx_resources ( adapter ) ;
e1000_free_all_tx_resources ( adapter ) ;
kfree ( tx_old ) ;
kfree ( rx_old ) ;
2006-09-27 12:54:14 -07:00
adapter - > rx_ring = rxdr ;
adapter - > tx_ring = txdr ;
2008-07-11 15:17:28 -07:00
err = e1000_up ( adapter ) ;
if ( err )
2006-06-27 09:06:28 -07:00
goto err_setup ;
2005-04-16 15:20:36 -07:00
}
2006-06-27 09:06:28 -07:00
clear_bit ( __E1000_RESETTING , & adapter - > flags ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
err_setup_tx :
2005-10-04 07:01:55 -04:00
e1000_free_all_rx_resources ( adapter ) ;
2005-04-16 15:20:36 -07:00
err_setup_rx :
adapter - > rx_ring = rx_old ;
adapter - > tx_ring = tx_old ;
2006-09-27 12:54:14 -07:00
kfree ( rxdr ) ;
err_alloc_rx :
kfree ( txdr ) ;
err_alloc_tx :
2005-04-16 15:20:36 -07:00
e1000_up ( adapter ) ;
2006-06-27 09:06:28 -07:00
err_setup :
clear_bit ( __E1000_RESETTING , & adapter - > flags ) ;
2005-04-16 15:20:36 -07:00
return err ;
}
2008-07-11 15:17:02 -07:00
static bool reg_pattern_test ( struct e1000_adapter * adapter , u64 * data , int reg ,
u32 mask , u32 write )
2007-11-13 20:52:05 -08:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
static const u32 test [ ] =
2007-11-13 20:52:05 -08:00
{ 0x5A5A5A5A , 0xA5A5A5A5 , 0x00000000 , 0xFFFFFFFF } ;
2008-07-11 15:17:08 -07:00
u8 __iomem * address = hw - > hw_addr + reg ;
2008-04-03 10:06:32 -07:00
u32 read ;
2007-11-13 20:52:05 -08:00
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( test ) ; i + + ) {
writel ( write & test [ i ] , address ) ;
read = readl ( address ) ;
if ( read ! = ( write & test [ i ] & mask ) ) {
2010-07-26 23:37:21 -07:00
e_err ( drv , " pattern test reg %04X failed: "
" got 0x%08X expected 0x%08X \n " ,
reg , read , ( write & test [ i ] & mask ) ) ;
2007-11-13 20:52:05 -08:00
* data = reg ;
return true ;
}
}
return false ;
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static bool reg_set_and_check ( struct e1000_adapter * adapter , u64 * data , int reg ,
u32 mask , u32 write )
2007-11-13 20:52:05 -08:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
u8 __iomem * address = hw - > hw_addr + reg ;
2008-04-03 10:06:32 -07:00
u32 read ;
2007-11-13 20:52:05 -08:00
writel ( write & mask , address ) ;
read = readl ( address ) ;
if ( ( read & mask ) ! = ( write & mask ) ) {
2010-07-26 23:37:21 -07:00
e_err ( drv , " set/check reg %04X test failed: "
2010-04-27 14:02:58 +00:00
" got 0x%08X expected 0x%08X \n " ,
reg , ( read & mask ) , ( write & mask ) ) ;
2007-11-13 20:52:05 -08:00
* data = reg ;
return true ;
}
return false ;
2005-04-16 15:20:36 -07:00
}
2007-11-13 20:52:05 -08:00
# define REG_PATTERN_TEST(reg, mask, write) \
do { \
if ( reg_pattern_test ( adapter , data , \
2008-07-11 15:17:08 -07:00
( hw - > mac_type > = e1000_82543 ) \
2007-11-13 20:52:05 -08:00
? E1000_ # # reg : E1000_82542_ # # reg , \
mask , write ) ) \
return 1 ; \
} while ( 0 )
# define REG_SET_AND_CHECK(reg, mask, write) \
do { \
if ( reg_set_and_check ( adapter , data , \
2008-07-11 15:17:08 -07:00
( hw - > mac_type > = e1000_82543 ) \
2007-11-13 20:52:05 -08:00
? E1000_ # # reg : E1000_82542_ # # reg , \
mask , write ) ) \
return 1 ; \
} while ( 0 )
2008-07-11 15:17:02 -07:00
static int e1000_reg_test ( struct e1000_adapter * adapter , u64 * data )
2005-04-16 15:20:36 -07:00
{
2008-04-03 10:06:32 -07:00
u32 value , before , after ;
u32 i , toggle ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-04-16 15:20:36 -07:00
/* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored .
*/
2009-09-25 12:16:14 +00:00
2005-10-04 06:58:59 -04:00
/* there are several bits on newer hardware that are r/w */
2009-09-25 12:16:14 +00:00
toggle = 0xFFFFF833 ;
2005-06-17 17:42:29 -07:00
2008-07-11 15:17:08 -07:00
before = er32 ( STATUS ) ;
value = ( er32 ( STATUS ) & toggle ) ;
ew32 ( STATUS , toggle ) ;
after = er32 ( STATUS ) & toggle ;
2006-01-18 13:01:39 -08:00
if ( value ! = after ) {
2010-07-26 23:37:21 -07:00
e_err ( drv , " failed STATUS register test got: "
2010-04-27 14:02:58 +00:00
" 0x%08X expected: 0x%08X \n " , after , value ) ;
2005-04-16 15:20:36 -07:00
* data = 1 ;
return 1 ;
}
2005-06-17 17:42:29 -07:00
/* restore previous status */
2008-07-11 15:17:08 -07:00
ew32 ( STATUS , before ) ;
2006-11-01 08:47:30 -08:00
2009-09-25 12:16:14 +00:00
REG_PATTERN_TEST ( FCAL , 0xFFFFFFFF , 0xFFFFFFFF ) ;
REG_PATTERN_TEST ( FCAH , 0x0000FFFF , 0xFFFFFFFF ) ;
REG_PATTERN_TEST ( FCT , 0x0000FFFF , 0xFFFFFFFF ) ;
REG_PATTERN_TEST ( VET , 0x0000FFFF , 0xFFFFFFFF ) ;
2006-11-01 08:47:30 -08:00
2005-04-16 15:20:36 -07:00
REG_PATTERN_TEST ( RDTR , 0x0000FFFF , 0xFFFFFFFF ) ;
REG_PATTERN_TEST ( RDBAH , 0xFFFFFFFF , 0xFFFFFFFF ) ;
REG_PATTERN_TEST ( RDLEN , 0x000FFF80 , 0x000FFFFF ) ;
REG_PATTERN_TEST ( RDH , 0x0000FFFF , 0x0000FFFF ) ;
REG_PATTERN_TEST ( RDT , 0x0000FFFF , 0x0000FFFF ) ;
REG_PATTERN_TEST ( FCRTH , 0x0000FFF8 , 0x0000FFF8 ) ;
REG_PATTERN_TEST ( FCTTV , 0x0000FFFF , 0x0000FFFF ) ;
REG_PATTERN_TEST ( TIPG , 0x3FFFFFFF , 0x3FFFFFFF ) ;
REG_PATTERN_TEST ( TDBAH , 0xFFFFFFFF , 0xFFFFFFFF ) ;
REG_PATTERN_TEST ( TDLEN , 0x000FFF80 , 0x000FFFFF ) ;
REG_SET_AND_CHECK ( RCTL , 0xFFFFFFFF , 0x00000000 ) ;
2006-11-01 08:47:30 -08:00
2009-09-25 12:16:14 +00:00
before = 0x06DFB3FE ;
2006-06-27 09:08:22 -07:00
REG_SET_AND_CHECK ( RCTL , before , 0x003FFFFB ) ;
2005-04-16 15:20:36 -07:00
REG_SET_AND_CHECK ( TCTL , 0xFFFFFFFF , 0x00000000 ) ;
2008-07-11 15:17:08 -07:00
if ( hw - > mac_type > = e1000_82543 ) {
2005-04-16 15:20:36 -07:00
2006-06-27 09:08:22 -07:00
REG_SET_AND_CHECK ( RCTL , before , 0xFFFFFFFF ) ;
2005-04-16 15:20:36 -07:00
REG_PATTERN_TEST ( RDBAL , 0xFFFFFFF0 , 0xFFFFFFFF ) ;
2009-09-25 12:16:14 +00:00
REG_PATTERN_TEST ( TXCW , 0xC000FFFF , 0x0000FFFF ) ;
2005-04-16 15:20:36 -07:00
REG_PATTERN_TEST ( TDBAL , 0xFFFFFFF0 , 0xFFFFFFFF ) ;
REG_PATTERN_TEST ( TIDV , 0x0000FFFF , 0x0000FFFF ) ;
2009-09-25 12:16:14 +00:00
value = E1000_RAR_ENTRIES ;
2006-06-27 09:08:22 -07:00
for ( i = 0 ; i < value ; i + + ) {
2005-04-16 15:20:36 -07:00
REG_PATTERN_TEST ( RA + ( ( ( i < < 1 ) + 1 ) < < 2 ) , 0x8003FFFF ,
2006-11-01 08:47:30 -08:00
0xFFFFFFFF ) ;
2005-04-16 15:20:36 -07:00
}
} else {
REG_SET_AND_CHECK ( RCTL , 0xFFFFFFFF , 0x01FFFFFF ) ;
REG_PATTERN_TEST ( RDBAL , 0xFFFFF000 , 0xFFFFFFFF ) ;
REG_PATTERN_TEST ( TXCW , 0x0000FFFF , 0x0000FFFF ) ;
REG_PATTERN_TEST ( TDBAL , 0xFFFFF000 , 0xFFFFFFFF ) ;
}
2009-09-25 12:16:14 +00:00
value = E1000_MC_TBL_SIZE ;
2006-06-27 09:08:22 -07:00
for ( i = 0 ; i < value ; i + + )
2005-04-16 15:20:36 -07:00
REG_PATTERN_TEST ( MTA + ( i < < 2 ) , 0xFFFFFFFF , 0xFFFFFFFF ) ;
* data = 0 ;
return 0 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_eeprom_test ( struct e1000_adapter * adapter , u64 * data )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u16 temp ;
u16 checksum = 0 ;
u16 i ;
2005-04-16 15:20:36 -07:00
* data = 0 ;
/* Read and add up the contents of the EEPROM */
2006-01-18 13:01:39 -08:00
for ( i = 0 ; i < ( EEPROM_CHECKSUM_REG + 1 ) ; i + + ) {
2008-07-11 15:17:08 -07:00
if ( ( e1000_read_eeprom ( hw , i , 1 , & temp ) ) < 0 ) {
2005-04-16 15:20:36 -07:00
* data = 1 ;
break ;
}
checksum + = temp ;
}
/* If Checksum is not Correct return error else test passed */
2008-07-11 15:17:18 -07:00
if ( ( checksum ! = ( u16 ) EEPROM_SUM ) & & ! ( * data ) )
2005-04-16 15:20:36 -07:00
* data = 2 ;
return * data ;
}
2008-07-11 15:17:02 -07:00
static irqreturn_t e1000_test_intr ( int irq , void * data )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:18 -07:00
struct net_device * netdev = ( struct net_device * ) data ;
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
adapter - > test_icr | = er32 ( ICR ) ;
2005-04-16 15:20:36 -07:00
return IRQ_HANDLED ;
}
2008-07-11 15:17:02 -07:00
static int e1000_intr_test ( struct e1000_adapter * adapter , u64 * data )
2005-04-16 15:20:36 -07:00
{
struct net_device * netdev = adapter - > netdev ;
2008-04-03 10:06:32 -07:00
u32 mask , i = 0 ;
2008-03-21 11:06:25 -07:00
bool shared_int = true ;
2008-04-03 10:06:32 -07:00
u32 irq = adapter - > pdev - > irq ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-04-16 15:20:36 -07:00
* data = 0 ;
2006-08-28 14:56:16 -07:00
/* NOTE: we don't test MSI interrupts here, yet */
2005-04-16 15:20:36 -07:00
/* Hook up test interrupt handler just for this test */
2009-11-18 23:29:17 -08:00
if ( ! request_irq ( irq , e1000_test_intr , IRQF_PROBE_SHARED , netdev - > name ,
2006-11-01 08:47:30 -08:00
netdev ) )
2008-03-21 11:06:25 -07:00
shared_int = false ;
2009-11-18 23:29:17 -08:00
else if ( request_irq ( irq , e1000_test_intr , IRQF_SHARED ,
2006-11-01 08:47:30 -08:00
netdev - > name , netdev ) ) {
2005-04-16 15:20:36 -07:00
* data = 1 ;
return - 1 ;
}
2010-07-26 23:37:21 -07:00
e_info ( hw , " testing %s interrupt \n " , ( shared_int ?
" shared " : " unshared " ) ) ;
2005-04-16 15:20:36 -07:00
/* Disable all the interrupts */
2008-07-11 15:17:08 -07:00
ew32 ( IMC , 0xFFFFFFFF ) ;
2006-09-19 15:27:07 -04:00
msleep ( 10 ) ;
2005-04-16 15:20:36 -07:00
/* Test each interrupt */
2006-01-18 13:01:39 -08:00
for ( ; i < 10 ; i + + ) {
2005-04-16 15:20:36 -07:00
/* Interrupt to test */
mask = 1 < < i ;
2006-05-23 13:36:06 -07:00
if ( ! shared_int ) {
/* Disable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted . If
* an interrupt was posted to the bus , the
* test failed .
*/
adapter - > test_icr = 0 ;
2008-07-11 15:17:08 -07:00
ew32 ( IMC , mask ) ;
ew32 ( ICS , mask ) ;
2006-09-19 15:27:07 -04:00
msleep ( 10 ) ;
2006-05-23 13:36:06 -07:00
if ( adapter - > test_icr & mask ) {
* data = 3 ;
break ;
}
2005-04-16 15:20:36 -07:00
}
/* Enable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted . If
* an interrupt was not posted to the bus , the
* test failed .
*/
adapter - > test_icr = 0 ;
2008-07-11 15:17:08 -07:00
ew32 ( IMS , mask ) ;
ew32 ( ICS , mask ) ;
2006-09-19 15:27:07 -04:00
msleep ( 10 ) ;
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
if ( ! ( adapter - > test_icr & mask ) ) {
2005-04-16 15:20:36 -07:00
* data = 4 ;
break ;
}
2006-05-23 13:36:06 -07:00
if ( ! shared_int ) {
2005-04-16 15:20:36 -07:00
/* Disable the other interrupts to be reported in
* the cause register and then force the other
* interrupts and see if any get posted . If
* an interrupt was posted to the bus , the
* test failed .
*/
adapter - > test_icr = 0 ;
2008-07-11 15:17:08 -07:00
ew32 ( IMC , ~ mask & 0x00007FFF ) ;
ew32 ( ICS , ~ mask & 0x00007FFF ) ;
2006-09-19 15:27:07 -04:00
msleep ( 10 ) ;
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
if ( adapter - > test_icr ) {
2005-04-16 15:20:36 -07:00
* data = 5 ;
break ;
}
}
}
/* Disable all the interrupts */
2008-07-11 15:17:08 -07:00
ew32 ( IMC , 0xFFFFFFFF ) ;
2006-09-19 15:27:07 -04:00
msleep ( 10 ) ;
2005-04-16 15:20:36 -07:00
/* Unhook test interrupt handler */
free_irq ( irq , netdev ) ;
return * data ;
}
2008-07-11 15:17:02 -07:00
static void e1000_free_desc_rings ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2005-10-04 07:01:55 -04:00
struct e1000_tx_ring * txdr = & adapter - > test_tx_ring ;
struct e1000_rx_ring * rxdr = & adapter - > test_rx_ring ;
2005-04-16 15:20:36 -07:00
struct pci_dev * pdev = adapter - > pdev ;
int i ;
2006-01-18 13:01:39 -08:00
if ( txdr - > desc & & txdr - > buffer_info ) {
for ( i = 0 ; i < txdr - > count ; i + + ) {
if ( txdr - > buffer_info [ i ] . dma )
2010-04-27 13:08:45 +00:00
dma_unmap_single ( & pdev - > dev ,
txdr - > buffer_info [ i ] . dma ,
2005-04-16 15:20:36 -07:00
txdr - > buffer_info [ i ] . length ,
2010-04-27 13:08:45 +00:00
DMA_TO_DEVICE ) ;
2006-01-18 13:01:39 -08:00
if ( txdr - > buffer_info [ i ] . skb )
2005-04-16 15:20:36 -07:00
dev_kfree_skb ( txdr - > buffer_info [ i ] . skb ) ;
}
}
2006-01-18 13:01:39 -08:00
if ( rxdr - > desc & & rxdr - > buffer_info ) {
for ( i = 0 ; i < rxdr - > count ; i + + ) {
if ( rxdr - > buffer_info [ i ] . dma )
2010-04-27 13:08:45 +00:00
dma_unmap_single ( & pdev - > dev ,
rxdr - > buffer_info [ i ] . dma ,
2005-04-16 15:20:36 -07:00
rxdr - > buffer_info [ i ] . length ,
2010-04-27 13:08:45 +00:00
DMA_FROM_DEVICE ) ;
2006-01-18 13:01:39 -08:00
if ( rxdr - > buffer_info [ i ] . skb )
2005-04-16 15:20:36 -07:00
dev_kfree_skb ( rxdr - > buffer_info [ i ] . skb ) ;
}
}
2006-01-12 16:51:01 -08:00
if ( txdr - > desc ) {
2010-04-27 13:08:45 +00:00
dma_free_coherent ( & pdev - > dev , txdr - > size , txdr - > desc ,
txdr - > dma ) ;
2005-11-08 15:59:30 -05:00
txdr - > desc = NULL ;
}
2006-01-12 16:51:01 -08:00
if ( rxdr - > desc ) {
2010-04-27 13:08:45 +00:00
dma_free_coherent ( & pdev - > dev , rxdr - > size , rxdr - > desc ,
rxdr - > dma ) ;
2005-11-08 15:59:30 -05:00
rxdr - > desc = NULL ;
}
2005-04-16 15:20:36 -07:00
2005-10-28 16:53:13 -04:00
kfree ( txdr - > buffer_info ) ;
2005-11-08 15:59:30 -05:00
txdr - > buffer_info = NULL ;
2005-10-28 16:53:13 -04:00
kfree ( rxdr - > buffer_info ) ;
2005-11-08 15:59:30 -05:00
rxdr - > buffer_info = NULL ;
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static int e1000_setup_desc_rings ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-10-04 07:01:55 -04:00
struct e1000_tx_ring * txdr = & adapter - > test_tx_ring ;
struct e1000_rx_ring * rxdr = & adapter - > test_rx_ring ;
2005-04-16 15:20:36 -07:00
struct pci_dev * pdev = adapter - > pdev ;
2008-04-03 10:06:32 -07:00
u32 rctl ;
2007-03-06 08:58:04 -08:00
int i , ret_val ;
2005-04-16 15:20:36 -07:00
/* Setup Tx descriptor ring and Tx buffers */
2006-01-18 13:01:39 -08:00
if ( ! txdr - > count )
txdr - > count = E1000_DEFAULT_TXD ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:28 -07:00
txdr - > buffer_info = kcalloc ( txdr - > count , sizeof ( struct e1000_buffer ) ,
GFP_KERNEL ) ;
if ( ! txdr - > buffer_info ) {
2005-04-16 15:20:36 -07:00
ret_val = 1 ;
goto err_nomem ;
}
txdr - > size = txdr - > count * sizeof ( struct e1000_tx_desc ) ;
2007-04-27 13:55:29 -07:00
txdr - > size = ALIGN ( txdr - > size , 4096 ) ;
2010-04-27 13:08:45 +00:00
txdr - > desc = dma_alloc_coherent ( & pdev - > dev , txdr - > size , & txdr - > dma ,
GFP_KERNEL ) ;
2008-07-11 15:17:28 -07:00
if ( ! txdr - > desc ) {
2005-04-16 15:20:36 -07:00
ret_val = 2 ;
goto err_nomem ;
}
memset ( txdr - > desc , 0 , txdr - > size ) ;
txdr - > next_to_use = txdr - > next_to_clean = 0 ;
2008-07-11 15:17:18 -07:00
ew32 ( TDBAL , ( ( u64 ) txdr - > dma & 0x00000000FFFFFFFF ) ) ;
ew32 ( TDBAH , ( ( u64 ) txdr - > dma > > 32 ) ) ;
2008-07-11 15:17:08 -07:00
ew32 ( TDLEN , txdr - > count * sizeof ( struct e1000_tx_desc ) ) ;
ew32 ( TDH , 0 ) ;
ew32 ( TDT , 0 ) ;
ew32 ( TCTL , E1000_TCTL_PSP | E1000_TCTL_EN |
E1000_COLLISION_THRESHOLD < < E1000_CT_SHIFT |
E1000_FDX_COLLISION_DISTANCE < < E1000_COLD_SHIFT ) ;
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
for ( i = 0 ; i < txdr - > count ; i + + ) {
2005-04-16 15:20:36 -07:00
struct e1000_tx_desc * tx_desc = E1000_TX_DESC ( * txdr , i ) ;
struct sk_buff * skb ;
unsigned int size = 1024 ;
2008-07-11 15:17:28 -07:00
skb = alloc_skb ( size , GFP_KERNEL ) ;
if ( ! skb ) {
2005-04-16 15:20:36 -07:00
ret_val = 3 ;
goto err_nomem ;
}
skb_put ( skb , size ) ;
txdr - > buffer_info [ i ] . skb = skb ;
txdr - > buffer_info [ i ] . length = skb - > len ;
txdr - > buffer_info [ i ] . dma =
2010-04-27 13:08:45 +00:00
dma_map_single ( & pdev - > dev , skb - > data , skb - > len ,
DMA_TO_DEVICE ) ;
2005-04-16 15:20:36 -07:00
tx_desc - > buffer_addr = cpu_to_le64 ( txdr - > buffer_info [ i ] . dma ) ;
tx_desc - > lower . data = cpu_to_le32 ( skb - > len ) ;
tx_desc - > lower . data | = cpu_to_le32 ( E1000_TXD_CMD_EOP |
E1000_TXD_CMD_IFCS |
E1000_TXD_CMD_RPS ) ;
tx_desc - > upper . data = 0 ;
}
/* Setup Rx descriptor ring and Rx buffers */
2006-01-18 13:01:39 -08:00
if ( ! rxdr - > count )
rxdr - > count = E1000_DEFAULT_RXD ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:28 -07:00
rxdr - > buffer_info = kcalloc ( rxdr - > count , sizeof ( struct e1000_buffer ) ,
GFP_KERNEL ) ;
if ( ! rxdr - > buffer_info ) {
2005-04-16 15:20:36 -07:00
ret_val = 4 ;
goto err_nomem ;
}
rxdr - > size = rxdr - > count * sizeof ( struct e1000_rx_desc ) ;
2010-04-27 13:08:45 +00:00
rxdr - > desc = dma_alloc_coherent ( & pdev - > dev , rxdr - > size , & rxdr - > dma ,
GFP_KERNEL ) ;
2008-07-11 15:17:28 -07:00
if ( ! rxdr - > desc ) {
2005-04-16 15:20:36 -07:00
ret_val = 5 ;
goto err_nomem ;
}
memset ( rxdr - > desc , 0 , rxdr - > size ) ;
rxdr - > next_to_use = rxdr - > next_to_clean = 0 ;
2008-07-11 15:17:08 -07:00
rctl = er32 ( RCTL ) ;
ew32 ( RCTL , rctl & ~ E1000_RCTL_EN ) ;
2008-07-11 15:17:18 -07:00
ew32 ( RDBAL , ( ( u64 ) rxdr - > dma & 0xFFFFFFFF ) ) ;
ew32 ( RDBAH , ( ( u64 ) rxdr - > dma > > 32 ) ) ;
2008-07-11 15:17:08 -07:00
ew32 ( RDLEN , rxdr - > size ) ;
ew32 ( RDH , 0 ) ;
ew32 ( RDT , 0 ) ;
2005-04-16 15:20:36 -07:00
rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
2008-07-11 15:17:08 -07:00
( hw - > mc_filter_type < < E1000_RCTL_MO_SHIFT ) ;
ew32 ( RCTL , rctl ) ;
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
for ( i = 0 ; i < rxdr - > count ; i + + ) {
2005-04-16 15:20:36 -07:00
struct e1000_rx_desc * rx_desc = E1000_RX_DESC ( * rxdr , i ) ;
struct sk_buff * skb ;
2008-07-11 15:17:28 -07:00
skb = alloc_skb ( E1000_RXBUFFER_2048 + NET_IP_ALIGN , GFP_KERNEL ) ;
if ( ! skb ) {
2005-04-16 15:20:36 -07:00
ret_val = 6 ;
goto err_nomem ;
}
skb_reserve ( skb , NET_IP_ALIGN ) ;
rxdr - > buffer_info [ i ] . skb = skb ;
rxdr - > buffer_info [ i ] . length = E1000_RXBUFFER_2048 ;
rxdr - > buffer_info [ i ] . dma =
2010-04-27 13:08:45 +00:00
dma_map_single ( & pdev - > dev , skb - > data ,
E1000_RXBUFFER_2048 , DMA_FROM_DEVICE ) ;
2005-04-16 15:20:36 -07:00
rx_desc - > buffer_addr = cpu_to_le64 ( rxdr - > buffer_info [ i ] . dma ) ;
memset ( skb - > data , 0x00 , skb - > len ) ;
}
return 0 ;
err_nomem :
e1000_free_desc_rings ( adapter ) ;
return ret_val ;
}
2008-07-11 15:17:02 -07:00
static void e1000_phy_disable_receiver ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-04-16 15:20:36 -07:00
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw , 29 , 0x001F ) ;
e1000_write_phy_reg ( hw , 30 , 0x8FFC ) ;
e1000_write_phy_reg ( hw , 29 , 0x001A ) ;
e1000_write_phy_reg ( hw , 30 , 0x8FF0 ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static void e1000_phy_reset_clk_and_crs ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u16 phy_reg ;
2005-04-16 15:20:36 -07:00
/* Because we reset the PHY above, we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25 MHz clock . This
* value defaults back to a 2.5 MHz clock when the PHY is reset .
*/
2008-07-11 15:17:08 -07:00
e1000_read_phy_reg ( hw , M88E1000_EXT_PHY_SPEC_CTRL , & phy_reg ) ;
2005-04-16 15:20:36 -07:00
phy_reg | = M88E1000_EPSCR_TX_CLK_25 ;
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw ,
2005-04-16 15:20:36 -07:00
M88E1000_EXT_PHY_SPEC_CTRL , phy_reg ) ;
/* In addition, because of the s/w reset above, we need to enable
* CRS on TX . This must be set for both full and half duplex
* operation .
*/
2008-07-11 15:17:08 -07:00
e1000_read_phy_reg ( hw , M88E1000_PHY_SPEC_CTRL , & phy_reg ) ;
2005-04-16 15:20:36 -07:00
phy_reg | = M88E1000_PSCR_ASSERT_CRS_ON_TX ;
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw ,
2005-04-16 15:20:36 -07:00
M88E1000_PHY_SPEC_CTRL , phy_reg ) ;
}
2008-07-11 15:17:02 -07:00
static int e1000_nonintegrated_phy_loopback ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u32 ctrl_reg ;
u16 phy_reg ;
2005-04-16 15:20:36 -07:00
/* Setup the Device Control Register for PHY loopback test. */
2008-07-11 15:17:08 -07:00
ctrl_reg = er32 ( CTRL ) ;
2005-04-16 15:20:36 -07:00
ctrl_reg | = ( E1000_CTRL_ILOS | /* Invert Loss-Of-Signal */
E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */
E1000_CTRL_FD ) ; /* Force Duplex to FULL */
2008-07-11 15:17:08 -07:00
ew32 ( CTRL , ctrl_reg ) ;
2005-04-16 15:20:36 -07:00
/* Read the PHY Specific Control Register (0x10) */
2008-07-11 15:17:08 -07:00
e1000_read_phy_reg ( hw , M88E1000_PHY_SPEC_CTRL , & phy_reg ) ;
2005-04-16 15:20:36 -07:00
/* Clear Auto-Crossover bits in PHY Specific Control Register
* ( bits 6 : 5 ) .
*/
phy_reg & = ~ M88E1000_PSCR_AUTO_X_MODE ;
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw , M88E1000_PHY_SPEC_CTRL , phy_reg ) ;
2005-04-16 15:20:36 -07:00
/* Perform software reset on the PHY */
2008-07-11 15:17:08 -07:00
e1000_phy_reset ( hw ) ;
2005-04-16 15:20:36 -07:00
/* Have to setup TX_CLK and TX_CRS after software reset */
e1000_phy_reset_clk_and_crs ( adapter ) ;
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw , PHY_CTRL , 0x8100 ) ;
2005-04-16 15:20:36 -07:00
/* Wait for reset to complete. */
udelay ( 500 ) ;
/* Have to setup TX_CLK and TX_CRS after software reset */
e1000_phy_reset_clk_and_crs ( adapter ) ;
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
e1000_phy_disable_receiver ( adapter ) ;
/* Set the loopback bit in the PHY control register. */
2008-07-11 15:17:08 -07:00
e1000_read_phy_reg ( hw , PHY_CTRL , & phy_reg ) ;
2005-04-16 15:20:36 -07:00
phy_reg | = MII_CR_LOOPBACK ;
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw , PHY_CTRL , phy_reg ) ;
2005-04-16 15:20:36 -07:00
/* Setup TX_CLK and TX_CRS one more time. */
e1000_phy_reset_clk_and_crs ( adapter ) ;
/* Check Phy Configuration */
2008-07-11 15:17:08 -07:00
e1000_read_phy_reg ( hw , PHY_CTRL , & phy_reg ) ;
2006-01-18 13:01:39 -08:00
if ( phy_reg ! = 0x4100 )
2005-04-16 15:20:36 -07:00
return 9 ;
2008-07-11 15:17:08 -07:00
e1000_read_phy_reg ( hw , M88E1000_EXT_PHY_SPEC_CTRL , & phy_reg ) ;
2006-01-18 13:01:39 -08:00
if ( phy_reg ! = 0x0070 )
2005-04-16 15:20:36 -07:00
return 10 ;
2008-07-11 15:17:08 -07:00
e1000_read_phy_reg ( hw , 29 , & phy_reg ) ;
2006-01-18 13:01:39 -08:00
if ( phy_reg ! = 0x001A )
2005-04-16 15:20:36 -07:00
return 11 ;
return 0 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_integrated_phy_loopback ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u32 ctrl_reg = 0 ;
u32 stat_reg = 0 ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
hw - > autoneg = false ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
if ( hw - > phy_type = = e1000_phy_m88 ) {
2005-04-16 15:20:36 -07:00
/* Auto-MDI/MDIX Off */
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw ,
2005-04-16 15:20:36 -07:00
M88E1000_PHY_SPEC_CTRL , 0x0808 ) ;
/* reset to update Auto-MDI/MDIX */
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw , PHY_CTRL , 0x9140 ) ;
2005-04-16 15:20:36 -07:00
/* autoneg off */
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw , PHY_CTRL , 0x8140 ) ;
2009-09-25 12:16:14 +00:00
}
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
ctrl_reg = er32 ( CTRL ) ;
2006-06-27 09:08:22 -07:00
2009-09-25 12:16:14 +00:00
/* force 1000, set loopback */
e1000_write_phy_reg ( hw , PHY_CTRL , 0x4140 ) ;
2006-06-27 09:08:22 -07:00
2009-09-25 12:16:14 +00:00
/* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg = er32 ( CTRL ) ;
ctrl_reg & = ~ E1000_CTRL_SPD_SEL ; /* Clear the speed sel bits */
ctrl_reg | = ( E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */
E1000_CTRL_FD ) ; /* Force Duplex to FULL */
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
if ( hw - > media_type = = e1000_media_type_copper & &
hw - > phy_type = = e1000_phy_m88 )
2005-04-16 15:20:36 -07:00
ctrl_reg | = E1000_CTRL_ILOS ; /* Invert Loss of Signal */
2006-08-28 14:56:16 -07:00
else {
2005-04-16 15:20:36 -07:00
/* Set the ILOS bit on the fiber Nic is half
* duplex link is detected . */
2008-07-11 15:17:08 -07:00
stat_reg = er32 ( STATUS ) ;
2006-01-18 13:01:39 -08:00
if ( ( stat_reg & E1000_STATUS_FD ) = = 0 )
2005-04-16 15:20:36 -07:00
ctrl_reg | = ( E1000_CTRL_ILOS | E1000_CTRL_SLU ) ;
}
2008-07-11 15:17:08 -07:00
ew32 ( CTRL , ctrl_reg ) ;
2005-04-16 15:20:36 -07:00
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC .
*/
2008-07-11 15:17:08 -07:00
if ( hw - > phy_type = = e1000_phy_m88 )
2005-04-16 15:20:36 -07:00
e1000_phy_disable_receiver ( adapter ) ;
udelay ( 500 ) ;
return 0 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_set_phy_loopback ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u16 phy_reg = 0 ;
u16 count = 0 ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
switch ( hw - > mac_type ) {
2005-04-16 15:20:36 -07:00
case e1000_82543 :
2008-07-11 15:17:08 -07:00
if ( hw - > media_type = = e1000_media_type_copper ) {
2005-04-16 15:20:36 -07:00
/* Attempt to setup Loopback mode on Non-integrated PHY.
* Some PHY registers get corrupted at random , so
* attempt this 10 times .
*/
2006-01-18 13:01:39 -08:00
while ( e1000_nonintegrated_phy_loopback ( adapter ) & &
2005-04-16 15:20:36 -07:00
count + + < 10 ) ;
2006-01-18 13:01:39 -08:00
if ( count < 11 )
2005-04-16 15:20:36 -07:00
return 0 ;
}
break ;
case e1000_82544 :
case e1000_82540 :
case e1000_82545 :
case e1000_82545_rev_3 :
case e1000_82546 :
case e1000_82546_rev_3 :
case e1000_82541 :
case e1000_82541_rev_2 :
case e1000_82547 :
case e1000_82547_rev_2 :
return e1000_integrated_phy_loopback ( adapter ) ;
break ;
default :
/* Default PHY loopback work is to read the MII
* control register and assert bit 14 ( loopback mode ) .
*/
2008-07-11 15:17:08 -07:00
e1000_read_phy_reg ( hw , PHY_CTRL , & phy_reg ) ;
2005-04-16 15:20:36 -07:00
phy_reg | = MII_CR_LOOPBACK ;
2008-07-11 15:17:08 -07:00
e1000_write_phy_reg ( hw , PHY_CTRL , phy_reg ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
break ;
}
return 8 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_setup_loopback_test ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2006-01-12 16:50:44 -08:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u32 rctl ;
2005-04-16 15:20:36 -07:00
2006-01-12 16:50:44 -08:00
if ( hw - > media_type = = e1000_media_type_fiber | |
hw - > media_type = = e1000_media_type_internal_serdes ) {
switch ( hw - > mac_type ) {
case e1000_82545 :
case e1000_82546 :
case e1000_82545_rev_3 :
case e1000_82546_rev_3 :
2005-04-16 15:20:36 -07:00
return e1000_set_phy_loopback ( adapter ) ;
2006-01-12 16:50:44 -08:00
break ;
default :
2008-07-11 15:17:08 -07:00
rctl = er32 ( RCTL ) ;
2005-04-16 15:20:36 -07:00
rctl | = E1000_RCTL_LBM_TCVR ;
2008-07-11 15:17:08 -07:00
ew32 ( RCTL , rctl ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2006-01-12 16:50:44 -08:00
} else if ( hw - > media_type = = e1000_media_type_copper )
2005-04-16 15:20:36 -07:00
return e1000_set_phy_loopback ( adapter ) ;
return 7 ;
}
2008-07-11 15:17:02 -07:00
static void e1000_loopback_cleanup ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2006-01-12 16:50:44 -08:00
struct e1000_hw * hw = & adapter - > hw ;
2008-04-03 10:06:32 -07:00
u32 rctl ;
u16 phy_reg ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
rctl = er32 ( RCTL ) ;
2005-04-16 15:20:36 -07:00
rctl & = ~ ( E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC ) ;
2008-07-11 15:17:08 -07:00
ew32 ( RCTL , rctl ) ;
2005-04-16 15:20:36 -07:00
2006-01-12 16:50:44 -08:00
switch ( hw - > mac_type ) {
case e1000_82545 :
case e1000_82546 :
case e1000_82545_rev_3 :
case e1000_82546_rev_3 :
default :
2008-03-21 11:06:25 -07:00
hw - > autoneg = true ;
2006-01-12 16:50:44 -08:00
e1000_read_phy_reg ( hw , PHY_CTRL , & phy_reg ) ;
if ( phy_reg & MII_CR_LOOPBACK ) {
2005-04-16 15:20:36 -07:00
phy_reg & = ~ MII_CR_LOOPBACK ;
2006-01-12 16:50:44 -08:00
e1000_write_phy_reg ( hw , PHY_CTRL , phy_reg ) ;
e1000_phy_reset ( hw ) ;
2005-04-16 15:20:36 -07:00
}
2006-01-12 16:50:44 -08:00
break ;
2005-04-16 15:20:36 -07:00
}
}
2008-07-11 15:17:02 -07:00
static void e1000_create_lbtest_frame ( struct sk_buff * skb ,
unsigned int frame_size )
2005-04-16 15:20:36 -07:00
{
memset ( skb - > data , 0xFF , frame_size ) ;
2006-01-12 16:51:12 -08:00
frame_size & = ~ 1 ;
2005-04-16 15:20:36 -07:00
memset ( & skb - > data [ frame_size / 2 ] , 0xAA , frame_size / 2 - 1 ) ;
memset ( & skb - > data [ frame_size / 2 + 10 ] , 0xBE , 1 ) ;
memset ( & skb - > data [ frame_size / 2 + 12 ] , 0xAF , 1 ) ;
}
2008-07-11 15:17:02 -07:00
static int e1000_check_lbtest_frame ( struct sk_buff * skb ,
unsigned int frame_size )
2005-04-16 15:20:36 -07:00
{
2006-01-12 16:51:12 -08:00
frame_size & = ~ 1 ;
2006-01-18 13:01:39 -08:00
if ( * ( skb - > data + 3 ) = = 0xFF ) {
if ( ( * ( skb - > data + frame_size / 2 + 10 ) = = 0xBE ) & &
2005-04-16 15:20:36 -07:00
( * ( skb - > data + frame_size / 2 + 12 ) = = 0xAF ) ) {
return 0 ;
}
}
return 13 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_run_loopback_test ( struct e1000_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-10-04 07:01:55 -04:00
struct e1000_tx_ring * txdr = & adapter - > test_tx_ring ;
struct e1000_rx_ring * rxdr = & adapter - > test_rx_ring ;
2005-04-16 15:20:36 -07:00
struct pci_dev * pdev = adapter - > pdev ;
2005-04-28 19:38:30 -07:00
int i , j , k , l , lc , good_cnt , ret_val = 0 ;
unsigned long time ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
ew32 ( RDT , rxdr - > count - 1 ) ;
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
/* Calculate the loop count based on the largest descriptor ring
2005-04-28 19:38:30 -07:00
* The idea is to wrap the largest ring a number of times using 64
* send / receive pairs during each loop
*/
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
if ( rxdr - > count < = txdr - > count )
2005-04-28 19:38:30 -07:00
lc = ( ( txdr - > count / 64 ) * 2 ) + 1 ;
else
lc = ( ( rxdr - > count / 64 ) * 2 ) + 1 ;
k = l = 0 ;
2006-01-18 13:01:39 -08:00
for ( j = 0 ; j < = lc ; j + + ) { /* loop count loop */
for ( i = 0 ; i < 64 ; i + + ) { /* send the packets */
e1000_create_lbtest_frame ( txdr - > buffer_info [ i ] . skb ,
2005-04-28 19:38:30 -07:00
1024 ) ;
2010-04-27 13:08:45 +00:00
dma_sync_single_for_device ( & pdev - > dev ,
txdr - > buffer_info [ k ] . dma ,
txdr - > buffer_info [ k ] . length ,
DMA_TO_DEVICE ) ;
2006-01-18 13:01:39 -08:00
if ( unlikely ( + + k = = txdr - > count ) ) k = 0 ;
2005-04-28 19:38:30 -07:00
}
2008-07-11 15:17:08 -07:00
ew32 ( TDT , k ) ;
2006-09-19 15:27:07 -04:00
msleep ( 200 ) ;
2005-04-28 19:38:30 -07:00
time = jiffies ; /* set the start time for the receive */
good_cnt = 0 ;
do { /* receive the sent packets */
2010-04-27 13:08:45 +00:00
dma_sync_single_for_cpu ( & pdev - > dev ,
rxdr - > buffer_info [ l ] . dma ,
rxdr - > buffer_info [ l ] . length ,
DMA_FROM_DEVICE ) ;
2006-01-18 13:01:39 -08:00
2005-04-28 19:38:30 -07:00
ret_val = e1000_check_lbtest_frame (
rxdr - > buffer_info [ l ] . skb ,
1024 ) ;
2006-01-18 13:01:39 -08:00
if ( ! ret_val )
2005-04-28 19:38:30 -07:00
good_cnt + + ;
2006-01-18 13:01:39 -08:00
if ( unlikely ( + + l = = rxdr - > count ) ) l = 0 ;
/* time + 20 msecs (200 msecs on 2.4) is more than
* enough time to complete the receives , if it ' s
2005-04-28 19:38:30 -07:00
* exceeded , break and error off
*/
} while ( good_cnt < 64 & & jiffies < ( time + 20 ) ) ;
2006-01-18 13:01:39 -08:00
if ( good_cnt ! = 64 ) {
2005-04-28 19:38:30 -07:00
ret_val = 13 ; /* ret_val is the same as mis-compare */
2006-01-18 13:01:39 -08:00
break ;
2005-04-28 19:38:30 -07:00
}
2006-01-18 13:01:39 -08:00
if ( jiffies > = ( time + 2 ) ) {
2005-04-28 19:38:30 -07:00
ret_val = 14 ; /* error code for time out error */
break ;
}
} /* end loop count loop */
2005-04-16 15:20:36 -07:00
return ret_val ;
}
2008-07-11 15:17:02 -07:00
static int e1000_loopback_test ( struct e1000_adapter * adapter , u64 * data )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:28 -07:00
* data = e1000_setup_desc_rings ( adapter ) ;
if ( * data )
2006-01-12 16:50:28 -08:00
goto out ;
2008-07-11 15:17:28 -07:00
* data = e1000_setup_loopback_test ( adapter ) ;
if ( * data )
2006-01-12 16:50:28 -08:00
goto err_loopback ;
2005-04-16 15:20:36 -07:00
* data = e1000_run_loopback_test ( adapter ) ;
e1000_loopback_cleanup ( adapter ) ;
2006-01-12 16:50:28 -08:00
2005-04-16 15:20:36 -07:00
err_loopback :
2006-01-12 16:50:28 -08:00
e1000_free_desc_rings ( adapter ) ;
out :
2005-04-16 15:20:36 -07:00
return * data ;
}
2008-07-11 15:17:02 -07:00
static int e1000_link_test ( struct e1000_adapter * adapter , u64 * data )
2005-04-16 15:20:36 -07:00
{
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-04-16 15:20:36 -07:00
* data = 0 ;
2008-07-11 15:17:08 -07:00
if ( hw - > media_type = = e1000_media_type_internal_serdes ) {
2005-04-16 15:20:36 -07:00
int i = 0 ;
2009-09-25 12:17:44 +00:00
hw - > serdes_has_link = false ;
2005-04-16 15:20:36 -07:00
2005-04-28 19:44:46 -07:00
/* On some blade server designs, link establishment
* could take as long as 2 - 3 minutes */
2005-04-16 15:20:36 -07:00
do {
2008-07-11 15:17:08 -07:00
e1000_check_for_link ( hw ) ;
2009-09-25 12:17:44 +00:00
if ( hw - > serdes_has_link )
2005-04-16 15:20:36 -07:00
return * data ;
2006-09-19 15:27:07 -04:00
msleep ( 20 ) ;
2005-04-16 15:20:36 -07:00
} while ( i + + < 3750 ) ;
2005-04-28 19:44:46 -07:00
* data = 1 ;
2005-04-16 15:20:36 -07:00
} else {
2008-07-11 15:17:08 -07:00
e1000_check_for_link ( hw ) ;
if ( hw - > autoneg ) /* if auto_neg is set wait for it */
2006-09-19 15:27:07 -04:00
msleep ( 4000 ) ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
if ( ! ( er32 ( STATUS ) & E1000_STATUS_LU ) ) {
2005-04-16 15:20:36 -07:00
* data = 1 ;
}
}
return * data ;
}
2008-07-11 15:17:02 -07:00
static int e1000_get_sset_count ( struct net_device * netdev , int sset )
2005-04-16 15:20:36 -07:00
{
2007-10-03 18:07:32 -07:00
switch ( sset ) {
case ETH_SS_TEST :
return E1000_TEST_LEN ;
case ETH_SS_STATS :
return E1000_STATS_LEN ;
default :
return - EOPNOTSUPP ;
}
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static void e1000_diag_test ( struct net_device * netdev ,
struct ethtool_test * eth_test , u64 * data )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2008-03-21 11:06:25 -07:00
bool if_running = netif_running ( netdev ) ;
2005-04-16 15:20:36 -07:00
2006-09-27 12:54:02 -07:00
set_bit ( __E1000_TESTING , & adapter - > flags ) ;
2006-01-18 13:01:39 -08:00
if ( eth_test - > flags = = ETH_TEST_FL_OFFLINE ) {
2005-04-16 15:20:36 -07:00
/* Offline tests */
/* save speed, duplex, autoneg settings */
2008-07-11 15:17:08 -07:00
u16 autoneg_advertised = hw - > autoneg_advertised ;
u8 forced_speed_duplex = hw - > forced_speed_duplex ;
u8 autoneg = hw - > autoneg ;
2005-04-16 15:20:36 -07:00
2010-07-26 23:37:21 -07:00
e_info ( hw , " offline testing starting \n " ) ;
2006-08-16 13:31:33 -07:00
2005-04-16 15:20:36 -07:00
/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result */
2006-01-18 13:01:39 -08:00
if ( e1000_link_test ( adapter , & data [ 4 ] ) )
2005-04-16 15:20:36 -07:00
eth_test - > flags | = ETH_TEST_FL_FAILED ;
2006-01-18 13:01:39 -08:00
if ( if_running )
2006-06-27 09:06:28 -07:00
/* indicate we're in test mode */
dev_close ( netdev ) ;
2005-04-16 15:20:36 -07:00
else
e1000_reset ( adapter ) ;
2006-01-18 13:01:39 -08:00
if ( e1000_reg_test ( adapter , & data [ 0 ] ) )
2005-04-16 15:20:36 -07:00
eth_test - > flags | = ETH_TEST_FL_FAILED ;
e1000_reset ( adapter ) ;
2006-01-18 13:01:39 -08:00
if ( e1000_eeprom_test ( adapter , & data [ 1 ] ) )
2005-04-16 15:20:36 -07:00
eth_test - > flags | = ETH_TEST_FL_FAILED ;
e1000_reset ( adapter ) ;
2006-01-18 13:01:39 -08:00
if ( e1000_intr_test ( adapter , & data [ 2 ] ) )
2005-04-16 15:20:36 -07:00
eth_test - > flags | = ETH_TEST_FL_FAILED ;
e1000_reset ( adapter ) ;
2006-08-16 13:31:33 -07:00
/* make sure the phy is powered up */
e1000_power_up_phy ( adapter ) ;
2006-01-18 13:01:39 -08:00
if ( e1000_loopback_test ( adapter , & data [ 3 ] ) )
2005-04-16 15:20:36 -07:00
eth_test - > flags | = ETH_TEST_FL_FAILED ;
/* restore speed, duplex, autoneg settings */
2008-07-11 15:17:08 -07:00
hw - > autoneg_advertised = autoneg_advertised ;
hw - > forced_speed_duplex = forced_speed_duplex ;
hw - > autoneg = autoneg ;
2005-04-16 15:20:36 -07:00
e1000_reset ( adapter ) ;
2006-09-27 12:54:02 -07:00
clear_bit ( __E1000_TESTING , & adapter - > flags ) ;
2006-01-18 13:01:39 -08:00
if ( if_running )
2006-06-27 09:06:28 -07:00
dev_open ( netdev ) ;
2005-04-16 15:20:36 -07:00
} else {
2010-07-26 23:37:21 -07:00
e_info ( hw , " online testing starting \n " ) ;
2005-04-16 15:20:36 -07:00
/* Online tests */
2006-01-18 13:01:39 -08:00
if ( e1000_link_test ( adapter , & data [ 4 ] ) )
2005-04-16 15:20:36 -07:00
eth_test - > flags | = ETH_TEST_FL_FAILED ;
2006-11-01 08:47:30 -08:00
/* Online tests aren't run; pass by default */
2005-04-16 15:20:36 -07:00
data [ 0 ] = 0 ;
data [ 1 ] = 0 ;
data [ 2 ] = 0 ;
data [ 3 ] = 0 ;
2006-06-27 09:06:28 -07:00
2006-09-27 12:54:02 -07:00
clear_bit ( __E1000_TESTING , & adapter - > flags ) ;
2005-04-16 15:20:36 -07:00
}
2005-10-04 07:07:24 -04:00
msleep_interruptible ( 4 * 1000 ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static int e1000_wol_exclusion ( struct e1000_adapter * adapter ,
struct ethtool_wolinfo * wol )
2005-04-16 15:20:36 -07:00
{
struct e1000_hw * hw = & adapter - > hw ;
2006-08-31 14:27:46 -07:00
int retval = 1 ; /* fail by default */
2005-04-16 15:20:36 -07:00
2006-08-31 14:27:46 -07:00
switch ( hw - > device_id ) {
2006-10-24 14:45:55 -07:00
case E1000_DEV_ID_82542 :
2005-04-16 15:20:36 -07:00
case E1000_DEV_ID_82543GC_FIBER :
case E1000_DEV_ID_82543GC_COPPER :
case E1000_DEV_ID_82544EI_FIBER :
case E1000_DEV_ID_82546EB_QUAD_COPPER :
case E1000_DEV_ID_82545EM_FIBER :
case E1000_DEV_ID_82545EM_COPPER :
2006-03-02 18:18:48 -08:00
case E1000_DEV_ID_82546GB_QUAD_COPPER :
2006-08-31 14:27:46 -07:00
case E1000_DEV_ID_82546GB_PCIE :
/* these don't support WoL at all */
2005-04-16 15:20:36 -07:00
wol - > supported = 0 ;
2006-08-31 14:27:46 -07:00
break ;
2005-04-16 15:20:36 -07:00
case E1000_DEV_ID_82546EB_FIBER :
case E1000_DEV_ID_82546GB_FIBER :
2006-08-31 14:27:46 -07:00
/* Wake events not supported on port B */
2008-07-11 15:17:08 -07:00
if ( er32 ( STATUS ) & E1000_STATUS_FUNC_1 ) {
2005-04-16 15:20:36 -07:00
wol - > supported = 0 ;
2006-08-31 14:27:46 -07:00
break ;
2005-04-16 15:20:36 -07:00
}
2006-08-31 14:27:46 -07:00
/* return success for non excluded adapter ports */
retval = 0 ;
break ;
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 :
/* quad port adapters only support WoL on port A */
if ( ! adapter - > quad_port_a ) {
wol - > supported = 0 ;
break ;
}
/* return success for non excluded adapter ports */
retval = 0 ;
break ;
2005-04-16 15:20:36 -07:00
default :
2006-08-31 14:27:46 -07:00
/* dual port cards only support WoL on port A from now on
* unless it was enabled in the eeprom for port B
* so exclude FUNC_1 ports from having WoL enabled */
2008-07-11 15:17:08 -07:00
if ( er32 ( STATUS ) & E1000_STATUS_FUNC_1 & &
2006-08-31 14:27:46 -07:00
! adapter - > eeprom_wol ) {
wol - > supported = 0 ;
break ;
}
2006-03-02 18:18:48 -08:00
2006-08-31 14:27:46 -07:00
retval = 0 ;
}
return retval ;
}
2008-07-11 15:17:02 -07:00
static void e1000_get_wol ( struct net_device * netdev ,
struct ethtool_wolinfo * wol )
2006-08-31 14:27:46 -07:00
{
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2006-08-31 14:27:46 -07:00
wol - > supported = WAKE_UCAST | WAKE_MCAST |
WAKE_BCAST | WAKE_MAGIC ;
wol - > wolopts = 0 ;
/* this function will set ->supported = 0 and return 1 if wol is not
* supported by this hardware */
2008-11-07 20:30:19 +00:00
if ( e1000_wol_exclusion ( adapter , wol ) | |
! device_can_wakeup ( & adapter - > pdev - > dev ) )
2005-04-16 15:20:36 -07:00
return ;
2006-08-31 14:27:46 -07:00
/* apply any specific unsupported masks here */
2008-07-11 15:17:08 -07:00
switch ( hw - > device_id ) {
2006-08-31 14:27:46 -07:00
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 :
/* KSP3 does not suppport UCAST wake-ups */
wol - > supported & = ~ WAKE_UCAST ;
if ( adapter - > wol & E1000_WUFC_EX )
2010-07-26 23:37:21 -07:00
e_err ( drv , " Interface does not support directed "
" (unicast) frame wake-up packets \n " ) ;
2006-08-31 14:27:46 -07:00
break ;
default :
break ;
2005-04-16 15:20:36 -07:00
}
2006-08-31 14:27:46 -07:00
if ( adapter - > wol & E1000_WUFC_EX )
wol - > wolopts | = WAKE_UCAST ;
if ( adapter - > wol & E1000_WUFC_MC )
wol - > wolopts | = WAKE_MCAST ;
if ( adapter - > wol & E1000_WUFC_BC )
wol - > wolopts | = WAKE_BCAST ;
if ( adapter - > wol & E1000_WUFC_MAG )
wol - > wolopts | = WAKE_MAGIC ;
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static int e1000_set_wol ( struct net_device * netdev , struct ethtool_wolinfo * wol )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2006-08-31 14:27:46 -07:00
if ( wol - > wolopts & ( WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE ) )
return - EOPNOTSUPP ;
2008-11-07 20:30:19 +00:00
if ( e1000_wol_exclusion ( adapter , wol ) | |
! device_can_wakeup ( & adapter - > pdev - > dev ) )
2005-04-16 15:20:36 -07:00
return wol - > wolopts ? - EOPNOTSUPP : 0 ;
2006-08-31 14:27:46 -07:00
switch ( hw - > device_id ) {
2006-03-02 18:18:48 -08:00
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 :
if ( wol - > wolopts & WAKE_UCAST ) {
2010-07-26 23:37:21 -07:00
e_err ( drv , " Interface does not support directed "
" (unicast) frame wake-up packets \n " ) ;
2006-03-02 18:18:48 -08:00
return - EOPNOTSUPP ;
}
2006-08-31 14:27:46 -07:00
break ;
2005-04-16 15:20:36 -07:00
default :
2006-08-31 14:27:46 -07:00
break ;
2005-04-16 15:20:36 -07:00
}
2006-08-31 14:27:46 -07:00
/* these settings will always override what we currently have */
adapter - > wol = 0 ;
if ( wol - > wolopts & WAKE_UCAST )
adapter - > wol | = E1000_WUFC_EX ;
if ( wol - > wolopts & WAKE_MCAST )
adapter - > wol | = E1000_WUFC_MC ;
if ( wol - > wolopts & WAKE_BCAST )
adapter - > wol | = E1000_WUFC_BC ;
if ( wol - > wolopts & WAKE_MAGIC )
adapter - > wol | = E1000_WUFC_MAG ;
2008-11-07 20:30:19 +00:00
device_set_wakeup_enable ( & adapter - > pdev - > dev , adapter - > wol ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
/* toggle LED 4 times per second = 2 "blinks" per second */
# define E1000_ID_INTERVAL (HZ / 4)
/* bit defines for adapter->led_status */
# define E1000_LED_ON 0
2008-07-11 15:17:02 -07:00
static void e1000_led_blink_callback ( unsigned long data )
2005-04-16 15:20:36 -07:00
{
struct e1000_adapter * adapter = ( struct e1000_adapter * ) data ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-04-16 15:20:36 -07:00
2006-01-18 13:01:39 -08:00
if ( test_and_change_bit ( E1000_LED_ON , & adapter - > led_status ) )
2008-07-11 15:17:08 -07:00
e1000_led_off ( hw ) ;
2005-04-16 15:20:36 -07:00
else
2008-07-11 15:17:08 -07:00
e1000_led_on ( hw ) ;
2005-04-16 15:20:36 -07:00
mod_timer ( & adapter - > blink_timer , jiffies + E1000_ID_INTERVAL ) ;
}
2008-07-11 15:17:02 -07:00
static int e1000_phys_id ( struct net_device * netdev , u32 data )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2008-07-11 15:17:08 -07:00
struct e1000_hw * hw = & adapter - > hw ;
2005-04-16 15:20:36 -07:00
2007-10-29 10:46:19 -07:00
if ( ! data )
data = INT_MAX ;
2005-04-16 15:20:36 -07:00
2009-09-25 12:16:14 +00:00
if ( ! adapter - > blink_timer . function ) {
init_timer ( & adapter - > blink_timer ) ;
adapter - > blink_timer . function = e1000_led_blink_callback ;
adapter - > blink_timer . data = ( unsigned long ) adapter ;
2005-04-16 15:20:36 -07:00
}
2009-09-25 12:16:14 +00:00
e1000_setup_led ( hw ) ;
mod_timer ( & adapter - > blink_timer , jiffies ) ;
msleep_interruptible ( data * 1000 ) ;
del_timer_sync ( & adapter - > blink_timer ) ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:17:08 -07:00
e1000_led_off ( hw ) ;
2005-04-16 15:20:36 -07:00
clear_bit ( E1000_LED_ON , & adapter - > led_status ) ;
2008-07-11 15:17:08 -07:00
e1000_cleanup_led ( hw ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2009-07-06 10:44:20 +00:00
static int e1000_get_coalesce ( struct net_device * netdev ,
struct ethtool_coalesce * ec )
{
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
if ( adapter - > hw . mac_type < e1000_82545 )
return - EOPNOTSUPP ;
2010-05-04 22:26:03 +00:00
if ( adapter - > itr_setting < = 4 )
2009-07-06 10:44:20 +00:00
ec - > rx_coalesce_usecs = adapter - > itr_setting ;
else
ec - > rx_coalesce_usecs = 1000000 / adapter - > itr_setting ;
return 0 ;
}
static int e1000_set_coalesce ( struct net_device * netdev ,
struct ethtool_coalesce * ec )
{
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
struct e1000_hw * hw = & adapter - > hw ;
if ( hw - > mac_type < e1000_82545 )
return - EOPNOTSUPP ;
if ( ( ec - > rx_coalesce_usecs > E1000_MAX_ITR_USECS ) | |
2010-05-04 22:26:03 +00:00
( ( ec - > rx_coalesce_usecs > 4 ) & &
2009-07-06 10:44:20 +00:00
( ec - > rx_coalesce_usecs < E1000_MIN_ITR_USECS ) ) | |
( ec - > rx_coalesce_usecs = = 2 ) )
return - EINVAL ;
2010-05-04 22:26:03 +00:00
if ( ec - > rx_coalesce_usecs = = 4 ) {
adapter - > itr = adapter - > itr_setting = 4 ;
} else if ( ec - > rx_coalesce_usecs < = 3 ) {
2009-07-06 10:44:20 +00:00
adapter - > itr = 20000 ;
adapter - > itr_setting = ec - > rx_coalesce_usecs ;
} else {
adapter - > itr = ( 1000000 / ec - > rx_coalesce_usecs ) ;
adapter - > itr_setting = adapter - > itr & ~ 3 ;
}
if ( adapter - > itr_setting ! = 0 )
ew32 ( ITR , 1000000000 / ( adapter - > itr * 256 ) ) ;
else
ew32 ( ITR , 0 ) ;
return 0 ;
}
2008-07-11 15:17:02 -07:00
static int e1000_nway_reset ( struct net_device * netdev )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2006-06-27 09:06:28 -07:00
if ( netif_running ( netdev ) )
e1000_reinit_locked ( adapter ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2008-07-11 15:17:02 -07:00
static void e1000_get_ethtool_stats ( struct net_device * netdev ,
struct ethtool_stats * stats , u64 * data )
2005-04-16 15:20:36 -07:00
{
2005-06-17 17:41:45 -07:00
struct e1000_adapter * adapter = netdev_priv ( netdev ) ;
2005-04-16 15:20:36 -07:00
int i ;
2009-10-13 01:45:48 +00:00
char * p = NULL ;
2005-04-16 15:20:36 -07:00
e1000_update_stats ( adapter ) ;
2006-01-12 16:50:41 -08:00
for ( i = 0 ; i < E1000_GLOBAL_STATS_LEN ; i + + ) {
2009-10-13 01:45:48 +00:00
switch ( e1000_gstrings_stats [ i ] . type ) {
case NETDEV_STATS :
p = ( char * ) netdev +
e1000_gstrings_stats [ i ] . stat_offset ;
break ;
case E1000_STATS :
p = ( char * ) adapter +
e1000_gstrings_stats [ i ] . stat_offset ;
break ;
}
2006-01-12 16:50:41 -08:00
data [ i ] = ( e1000_gstrings_stats [ i ] . sizeof_stat = =
2008-04-03 10:06:32 -07:00
sizeof ( u64 ) ) ? * ( u64 * ) p : * ( u32 * ) p ;
2005-04-16 15:20:36 -07:00
}
2006-01-12 16:50:41 -08:00
/* BUG_ON(i != E1000_STATS_LEN); */
2005-04-16 15:20:36 -07:00
}
2008-07-11 15:17:02 -07:00
static void e1000_get_strings ( struct net_device * netdev , u32 stringset ,
u8 * data )
2005-04-16 15:20:36 -07:00
{
2008-04-03 10:06:32 -07:00
u8 * p = data ;
2005-04-16 15:20:36 -07:00
int i ;
2006-01-18 13:01:39 -08:00
switch ( stringset ) {
2005-04-16 15:20:36 -07:00
case ETH_SS_TEST :
2006-01-18 13:01:39 -08:00
memcpy ( data , * e1000_gstrings_test ,
2007-12-05 11:57:30 -08:00
sizeof ( e1000_gstrings_test ) ) ;
2005-04-16 15:20:36 -07:00
break ;
case ETH_SS_STATS :
2006-01-12 16:50:41 -08:00
for ( i = 0 ; i < E1000_GLOBAL_STATS_LEN ; i + + ) {
memcpy ( p , e1000_gstrings_stats [ i ] . stat_string ,
ETH_GSTRING_LEN ) ;
p + = ETH_GSTRING_LEN ;
}
/* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */
2005-04-16 15:20:36 -07:00
break ;
}
}
2006-09-13 14:30:00 -04:00
static const struct ethtool_ops e1000_ethtool_ops = {
2005-04-16 15:20:36 -07:00
. get_settings = e1000_get_settings ,
. set_settings = e1000_set_settings ,
. get_drvinfo = e1000_get_drvinfo ,
. get_regs_len = e1000_get_regs_len ,
. get_regs = e1000_get_regs ,
. get_wol = e1000_get_wol ,
. set_wol = e1000_set_wol ,
2006-08-28 14:56:16 -07:00
. get_msglevel = e1000_get_msglevel ,
. set_msglevel = e1000_set_msglevel ,
2005-04-16 15:20:36 -07:00
. nway_reset = e1000_nway_reset ,
2010-02-03 14:49:28 +00:00
. get_link = e1000_get_link ,
2005-04-16 15:20:36 -07:00
. get_eeprom_len = e1000_get_eeprom_len ,
. get_eeprom = e1000_get_eeprom ,
. set_eeprom = e1000_set_eeprom ,
. get_ringparam = e1000_get_ringparam ,
. set_ringparam = e1000_set_ringparam ,
2006-08-28 14:56:16 -07:00
. get_pauseparam = e1000_get_pauseparam ,
. set_pauseparam = e1000_set_pauseparam ,
. get_rx_csum = e1000_get_rx_csum ,
. set_rx_csum = e1000_set_rx_csum ,
. get_tx_csum = e1000_get_tx_csum ,
. set_tx_csum = e1000_set_tx_csum ,
. set_sg = ethtool_op_set_sg ,
. set_tso = e1000_set_tso ,
2005-04-16 15:20:36 -07:00
. self_test = e1000_diag_test ,
. get_strings = e1000_get_strings ,
. phys_id = e1000_phys_id ,
. get_ethtool_stats = e1000_get_ethtool_stats ,
2009-07-06 10:44:20 +00:00
. get_sset_count = e1000_get_sset_count ,
. get_coalesce = e1000_get_coalesce ,
. set_coalesce = e1000_set_coalesce ,
2005-04-16 15:20:36 -07:00
} ;
void e1000_set_ethtool_ops ( struct net_device * netdev )
{
SET_ETHTOOL_OPS ( netdev , & e1000_ethtool_ops ) ;
}