2009-10-13 11:15:51 +04:00
/*
* Linux driver for VMware ' s vmxnet3 ethernet NIC .
*
2016-06-16 20:51:53 +03:00
* Copyright ( C ) 2008 - 2016 , VMware , Inc . All Rights Reserved .
2009-10-13 11:15:51 +04:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; version 2 of the License and no later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE , GOOD TITLE or
* NON INFRINGEMENT . See the GNU General Public License for more
* details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* The full GNU General Public License is included in this distribution in
* the file called " COPYING " .
*
2016-06-16 20:51:53 +03:00
* Maintained by : pv - drivers @ vmware . com
2009-10-13 11:15:51 +04:00
*
*/
# include "vmxnet3_int.h"
struct vmxnet3_stat_desc {
char desc [ ETH_GSTRING_LEN ] ;
int offset ;
} ;
/* per tq stats maintained by the device */
static const struct vmxnet3_stat_desc
vmxnet3_tq_dev_stats [ ] = {
/* description, offset */
2011-01-14 17:59:47 +03:00
{ " Tx Queue# " , 0 } ,
{ " TSO pkts tx " , offsetof ( struct UPT1_TxStats , TSOPktsTxOK ) } ,
{ " TSO bytes tx " , offsetof ( struct UPT1_TxStats , TSOBytesTxOK ) } ,
{ " ucast pkts tx " , offsetof ( struct UPT1_TxStats , ucastPktsTxOK ) } ,
{ " ucast bytes tx " , offsetof ( struct UPT1_TxStats , ucastBytesTxOK ) } ,
{ " mcast pkts tx " , offsetof ( struct UPT1_TxStats , mcastPktsTxOK ) } ,
{ " mcast bytes tx " , offsetof ( struct UPT1_TxStats , mcastBytesTxOK ) } ,
{ " bcast pkts tx " , offsetof ( struct UPT1_TxStats , bcastPktsTxOK ) } ,
{ " bcast bytes tx " , offsetof ( struct UPT1_TxStats , bcastBytesTxOK ) } ,
{ " pkts tx err " , offsetof ( struct UPT1_TxStats , pktsTxError ) } ,
{ " pkts tx discard " , offsetof ( struct UPT1_TxStats , pktsTxDiscard ) } ,
2009-10-13 11:15:51 +04:00
} ;
/* per tq stats maintained by the driver */
static const struct vmxnet3_stat_desc
vmxnet3_tq_driver_stats [ ] = {
/* description, offset */
2011-01-14 17:59:47 +03:00
{ " drv dropped tx total " , offsetof ( struct vmxnet3_tq_driver_stats ,
drop_total ) } ,
{ " too many frags " , offsetof ( struct vmxnet3_tq_driver_stats ,
drop_too_many_frags ) } ,
{ " giant hdr " , offsetof ( struct vmxnet3_tq_driver_stats ,
drop_oversized_hdr ) } ,
{ " hdr err " , offsetof ( struct vmxnet3_tq_driver_stats ,
drop_hdr_inspect_err ) } ,
{ " tso " , offsetof ( struct vmxnet3_tq_driver_stats ,
drop_tso ) } ,
{ " ring full " , offsetof ( struct vmxnet3_tq_driver_stats ,
tx_ring_full ) } ,
{ " pkts linearized " , offsetof ( struct vmxnet3_tq_driver_stats ,
linearized ) } ,
{ " hdr cloned " , offsetof ( struct vmxnet3_tq_driver_stats ,
copy_skb_header ) } ,
{ " giant hdr " , offsetof ( struct vmxnet3_tq_driver_stats ,
oversized_hdr ) } ,
2009-10-13 11:15:51 +04:00
} ;
/* per rq stats maintained by the device */
static const struct vmxnet3_stat_desc
vmxnet3_rq_dev_stats [ ] = {
2011-01-14 17:59:47 +03:00
{ " Rx Queue# " , 0 } ,
{ " LRO pkts rx " , offsetof ( struct UPT1_RxStats , LROPktsRxOK ) } ,
{ " LRO byte rx " , offsetof ( struct UPT1_RxStats , LROBytesRxOK ) } ,
{ " ucast pkts rx " , offsetof ( struct UPT1_RxStats , ucastPktsRxOK ) } ,
{ " ucast bytes rx " , offsetof ( struct UPT1_RxStats , ucastBytesRxOK ) } ,
{ " mcast pkts rx " , offsetof ( struct UPT1_RxStats , mcastPktsRxOK ) } ,
{ " mcast bytes rx " , offsetof ( struct UPT1_RxStats , mcastBytesRxOK ) } ,
{ " bcast pkts rx " , offsetof ( struct UPT1_RxStats , bcastPktsRxOK ) } ,
{ " bcast bytes rx " , offsetof ( struct UPT1_RxStats , bcastBytesRxOK ) } ,
{ " pkts rx OOB " , offsetof ( struct UPT1_RxStats , pktsRxOutOfBuf ) } ,
{ " pkts rx err " , offsetof ( struct UPT1_RxStats , pktsRxError ) } ,
2009-10-13 11:15:51 +04:00
} ;
/* per rq stats maintained by the driver */
static const struct vmxnet3_stat_desc
vmxnet3_rq_driver_stats [ ] = {
/* description, offset */
2011-01-14 17:59:47 +03:00
{ " drv dropped rx total " , offsetof ( struct vmxnet3_rq_driver_stats ,
drop_total ) } ,
{ " err " , offsetof ( struct vmxnet3_rq_driver_stats ,
drop_err ) } ,
{ " fcs " , offsetof ( struct vmxnet3_rq_driver_stats ,
drop_fcs ) } ,
{ " rx buf alloc fail " , offsetof ( struct vmxnet3_rq_driver_stats ,
rx_buf_alloc_failure ) } ,
2009-10-13 11:15:51 +04:00
} ;
2015-04-02 01:33:08 +03:00
/* global stats maintained by the driver */
2009-10-13 11:15:51 +04:00
static const struct vmxnet3_stat_desc
vmxnet3_global_stats [ ] = {
/* description, offset */
2011-01-14 17:59:47 +03:00
{ " tx timeout count " , offsetof ( struct vmxnet3_adapter ,
2009-10-13 11:15:51 +04:00
tx_timeout_count ) }
} ;
2011-06-08 18:53:57 +04:00
struct rtnl_link_stats64 *
vmxnet3_get_stats64 ( struct net_device * netdev ,
struct rtnl_link_stats64 * stats )
2009-10-13 11:15:51 +04:00
{
struct vmxnet3_adapter * adapter ;
struct vmxnet3_tq_driver_stats * drvTxStats ;
struct vmxnet3_rq_driver_stats * drvRxStats ;
struct UPT1_TxStats * devTxStats ;
struct UPT1_RxStats * devRxStats ;
2011-01-14 17:59:57 +03:00
unsigned long flags ;
2010-11-19 13:55:24 +03:00
int i ;
2009-10-13 11:15:51 +04:00
adapter = netdev_priv ( netdev ) ;
/* Collect the dev stats into the shared area */
2011-01-14 17:59:57 +03:00
spin_lock_irqsave ( & adapter - > cmd_lock , flags ) ;
2009-10-13 11:15:51 +04:00
VMXNET3_WRITE_BAR1_REG ( adapter , VMXNET3_REG_CMD , VMXNET3_CMD_GET_STATS ) ;
2011-01-14 17:59:57 +03:00
spin_unlock_irqrestore ( & adapter - > cmd_lock , flags ) ;
2009-10-13 11:15:51 +04:00
2010-11-19 13:55:24 +03:00
for ( i = 0 ; i < adapter - > num_tx_queues ; i + + ) {
devTxStats = & adapter - > tqd_start [ i ] . stats ;
drvTxStats = & adapter - > tx_queue [ i ] . stats ;
2011-06-08 18:53:57 +04:00
stats - > tx_packets + = devTxStats - > ucastPktsTxOK +
devTxStats - > mcastPktsTxOK +
devTxStats - > bcastPktsTxOK ;
stats - > tx_bytes + = devTxStats - > ucastBytesTxOK +
devTxStats - > mcastBytesTxOK +
devTxStats - > bcastBytesTxOK ;
stats - > tx_errors + = devTxStats - > pktsTxError ;
stats - > tx_dropped + = drvTxStats - > drop_total ;
2010-11-19 13:55:24 +03:00
}
2009-10-13 11:15:51 +04:00
2010-11-19 13:55:24 +03:00
for ( i = 0 ; i < adapter - > num_rx_queues ; i + + ) {
devRxStats = & adapter - > rqd_start [ i ] . stats ;
drvRxStats = & adapter - > rx_queue [ i ] . stats ;
2011-06-08 18:53:57 +04:00
stats - > rx_packets + = devRxStats - > ucastPktsRxOK +
devRxStats - > mcastPktsRxOK +
devRxStats - > bcastPktsRxOK ;
2009-10-13 11:15:51 +04:00
2011-06-08 18:53:57 +04:00
stats - > rx_bytes + = devRxStats - > ucastBytesRxOK +
devRxStats - > mcastBytesRxOK +
devRxStats - > bcastBytesRxOK ;
2009-10-13 11:15:51 +04:00
2011-06-08 18:53:57 +04:00
stats - > rx_errors + = devRxStats - > pktsRxError ;
stats - > rx_dropped + = drvRxStats - > drop_total ;
stats - > multicast + = devRxStats - > mcastPktsRxOK ;
2010-11-19 13:55:24 +03:00
}
2011-06-08 18:53:57 +04:00
return stats ;
2009-10-13 11:15:51 +04:00
}
static int
vmxnet3_get_sset_count ( struct net_device * netdev , int sset )
{
2011-01-14 17:59:47 +03:00
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
2009-10-13 11:15:51 +04:00
switch ( sset ) {
case ETH_SS_STATS :
2011-01-14 17:59:47 +03:00
return ( ARRAY_SIZE ( vmxnet3_tq_dev_stats ) +
ARRAY_SIZE ( vmxnet3_tq_driver_stats ) ) *
adapter - > num_tx_queues +
( ARRAY_SIZE ( vmxnet3_rq_dev_stats ) +
ARRAY_SIZE ( vmxnet3_rq_driver_stats ) ) *
adapter - > num_rx_queues +
2009-10-13 11:15:51 +04:00
ARRAY_SIZE ( vmxnet3_global_stats ) ;
default :
return - EOPNOTSUPP ;
}
}
2015-09-22 06:01:29 +03:00
/* This is a version 2 of the vmxnet3 ethtool_regs which goes hand in hand with
* the version 2 of the vmxnet3 support for ethtool ( 8 ) - - register - dump .
* Therefore , if any registers are added , removed or modified , then a version
* bump and a corresponding change in the vmxnet3 support for ethtool ( 8 )
* - - register - dump would be required .
*/
2009-10-13 11:15:51 +04:00
static int
vmxnet3_get_regs_len ( struct net_device * netdev )
{
2011-01-14 17:59:47 +03:00
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
2015-09-22 06:01:29 +03:00
return ( ( 9 /* BAR1 registers */ +
( 1 + adapter - > intr . num_intrs ) +
( 1 + adapter - > num_tx_queues * 17 /* Tx queue registers */ ) +
( 1 + adapter - > num_rx_queues * 23 /* Rx queue registers */ ) ) *
sizeof ( u32 ) ) ;
2009-10-13 11:15:51 +04:00
}
static void
vmxnet3_get_drvinfo ( struct net_device * netdev , struct ethtool_drvinfo * drvinfo )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
strlcpy ( drvinfo - > driver , vmxnet3_driver_name , sizeof ( drvinfo - > driver ) ) ;
strlcpy ( drvinfo - > version , VMXNET3_DRIVER_VERSION_REPORT ,
sizeof ( drvinfo - > version ) ) ;
strlcpy ( drvinfo - > bus_info , pci_name ( adapter - > pdev ) ,
2013-01-06 04:44:26 +04:00
sizeof ( drvinfo - > bus_info ) ) ;
2009-10-13 11:15:51 +04:00
}
static void
vmxnet3_get_strings ( struct net_device * netdev , u32 stringset , u8 * buf )
{
2011-01-14 17:59:47 +03:00
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
2009-10-13 11:15:51 +04:00
if ( stringset = = ETH_SS_STATS ) {
2011-01-14 17:59:47 +03:00
int i , j ;
for ( j = 0 ; j < adapter - > num_tx_queues ; j + + ) {
for ( i = 0 ; i < ARRAY_SIZE ( vmxnet3_tq_dev_stats ) ; i + + ) {
memcpy ( buf , vmxnet3_tq_dev_stats [ i ] . desc ,
ETH_GSTRING_LEN ) ;
buf + = ETH_GSTRING_LEN ;
}
for ( i = 0 ; i < ARRAY_SIZE ( vmxnet3_tq_driver_stats ) ;
i + + ) {
memcpy ( buf , vmxnet3_tq_driver_stats [ i ] . desc ,
ETH_GSTRING_LEN ) ;
buf + = ETH_GSTRING_LEN ;
}
2009-10-13 11:15:51 +04:00
}
2011-01-14 17:59:47 +03:00
for ( j = 0 ; j < adapter - > num_rx_queues ; j + + ) {
for ( i = 0 ; i < ARRAY_SIZE ( vmxnet3_rq_dev_stats ) ; i + + ) {
memcpy ( buf , vmxnet3_rq_dev_stats [ i ] . desc ,
ETH_GSTRING_LEN ) ;
buf + = ETH_GSTRING_LEN ;
}
for ( i = 0 ; i < ARRAY_SIZE ( vmxnet3_rq_driver_stats ) ;
i + + ) {
memcpy ( buf , vmxnet3_rq_driver_stats [ i ] . desc ,
ETH_GSTRING_LEN ) ;
buf + = ETH_GSTRING_LEN ;
}
2009-10-13 11:15:51 +04:00
}
2011-01-14 17:59:47 +03:00
2009-10-13 11:15:51 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( vmxnet3_global_stats ) ; i + + ) {
memcpy ( buf , vmxnet3_global_stats [ i ] . desc ,
ETH_GSTRING_LEN ) ;
buf + = ETH_GSTRING_LEN ;
}
}
}
2011-11-15 19:29:55 +04:00
int vmxnet3_set_features ( struct net_device * netdev , netdev_features_t features )
2010-06-28 03:29:42 +04:00
{
2009-10-13 11:15:51 +04:00
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
2011-01-14 17:59:57 +03:00
unsigned long flags ;
2011-11-15 19:29:55 +04:00
netdev_features_t changed = features ^ netdev - > features ;
2009-10-13 11:15:51 +04:00
2013-04-19 06:04:27 +04:00
if ( changed & ( NETIF_F_RXCSUM | NETIF_F_LRO |
NETIF_F_HW_VLAN_CTAG_RX ) ) {
2011-04-18 17:31:21 +04:00
if ( features & NETIF_F_RXCSUM )
adapter - > shared - > devRead . misc . uptFeatures | =
UPT1_F_RXCSUM ;
else
adapter - > shared - > devRead . misc . uptFeatures & =
~ UPT1_F_RXCSUM ;
2009-10-13 11:15:51 +04:00
2015-04-02 01:33:08 +03:00
/* update hardware LRO capability accordingly */
2011-04-18 17:31:21 +04:00
if ( features & NETIF_F_LRO )
2010-07-16 09:17:29 +04:00
adapter - > shared - > devRead . misc . uptFeatures | =
2010-10-21 22:05:32 +04:00
UPT1_F_LRO ;
2009-10-13 11:15:51 +04:00
else
adapter - > shared - > devRead . misc . uptFeatures & =
2010-10-21 22:05:32 +04:00
~ UPT1_F_LRO ;
2011-04-18 17:31:21 +04:00
2013-04-19 06:04:27 +04:00
if ( features & NETIF_F_HW_VLAN_CTAG_RX )
2011-06-23 17:04:39 +04:00
adapter - > shared - > devRead . misc . uptFeatures | =
UPT1_F_RXVLAN ;
else
adapter - > shared - > devRead . misc . uptFeatures & =
~ UPT1_F_RXVLAN ;
2011-01-14 17:59:57 +03:00
spin_lock_irqsave ( & adapter - > cmd_lock , flags ) ;
2009-10-13 11:15:51 +04:00
VMXNET3_WRITE_BAR1_REG ( adapter , VMXNET3_REG_CMD ,
VMXNET3_CMD_UPDATE_FEATURE ) ;
2011-01-14 17:59:57 +03:00
spin_unlock_irqrestore ( & adapter - > cmd_lock , flags ) ;
2009-10-13 11:15:51 +04:00
}
return 0 ;
}
static void
vmxnet3_get_ethtool_stats ( struct net_device * netdev ,
struct ethtool_stats * stats , u64 * buf )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
2011-01-14 17:59:57 +03:00
unsigned long flags ;
2009-10-13 11:15:51 +04:00
u8 * base ;
int i ;
2010-11-19 13:55:24 +03:00
int j = 0 ;
2009-10-13 11:15:51 +04:00
2011-01-14 17:59:57 +03:00
spin_lock_irqsave ( & adapter - > cmd_lock , flags ) ;
2009-10-13 11:15:51 +04:00
VMXNET3_WRITE_BAR1_REG ( adapter , VMXNET3_REG_CMD , VMXNET3_CMD_GET_STATS ) ;
2011-01-14 17:59:57 +03:00
spin_unlock_irqrestore ( & adapter - > cmd_lock , flags ) ;
2009-10-13 11:15:51 +04:00
/* this does assume each counter is 64-bit wide */
2011-01-14 17:59:47 +03:00
for ( j = 0 ; j < adapter - > num_tx_queues ; j + + ) {
base = ( u8 * ) & adapter - > tqd_start [ j ] . stats ;
* buf + + = ( u64 ) j ;
for ( i = 1 ; i < ARRAY_SIZE ( vmxnet3_tq_dev_stats ) ; i + + )
* buf + + = * ( u64 * ) ( base +
vmxnet3_tq_dev_stats [ i ] . offset ) ;
base = ( u8 * ) & adapter - > tx_queue [ j ] . stats ;
for ( i = 0 ; i < ARRAY_SIZE ( vmxnet3_tq_driver_stats ) ; i + + )
* buf + + = * ( u64 * ) ( base +
vmxnet3_tq_driver_stats [ i ] . offset ) ;
}
2009-10-13 11:15:51 +04:00
2015-01-15 22:54:30 +03:00
for ( j = 0 ; j < adapter - > num_rx_queues ; j + + ) {
2011-01-14 17:59:47 +03:00
base = ( u8 * ) & adapter - > rqd_start [ j ] . stats ;
* buf + + = ( u64 ) j ;
for ( i = 1 ; i < ARRAY_SIZE ( vmxnet3_rq_dev_stats ) ; i + + )
* buf + + = * ( u64 * ) ( base +
vmxnet3_rq_dev_stats [ i ] . offset ) ;
base = ( u8 * ) & adapter - > rx_queue [ j ] . stats ;
for ( i = 0 ; i < ARRAY_SIZE ( vmxnet3_rq_driver_stats ) ; i + + )
* buf + + = * ( u64 * ) ( base +
vmxnet3_rq_driver_stats [ i ] . offset ) ;
}
2009-10-13 11:15:51 +04:00
base = ( u8 * ) adapter ;
for ( i = 0 ; i < ARRAY_SIZE ( vmxnet3_global_stats ) ; i + + )
* buf + + = * ( u64 * ) ( base + vmxnet3_global_stats [ i ] . offset ) ;
}
2015-09-22 06:01:29 +03:00
/* This is a version 2 of the vmxnet3 ethtool_regs which goes hand in hand with
* the version 2 of the vmxnet3 support for ethtool ( 8 ) - - register - dump .
* Therefore , if any registers are added , removed or modified , then a version
* bump and a corresponding change in the vmxnet3 support for ethtool ( 8 )
* - - register - dump would be required .
*/
2009-10-13 11:15:51 +04:00
static void
vmxnet3_get_regs ( struct net_device * netdev , struct ethtool_regs * regs , void * p )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
u32 * buf = p ;
2011-01-14 17:59:47 +03:00
int i = 0 , j = 0 ;
2009-10-13 11:15:51 +04:00
memset ( p , 0 , vmxnet3_get_regs_len ( netdev ) ) ;
2015-09-22 06:01:29 +03:00
regs - > version = 2 ;
2009-10-13 11:15:51 +04:00
/* Update vmxnet3_get_regs_len if we want to dump more registers */
2015-09-22 06:01:29 +03:00
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_VRRS ) ;
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_UVRS ) ;
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_DSAL ) ;
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_DSAH ) ;
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_CMD ) ;
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_MACL ) ;
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_MACH ) ;
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_ICR ) ;
buf [ j + + ] = VMXNET3_READ_BAR1_REG ( adapter , VMXNET3_REG_ECR ) ;
buf [ j + + ] = adapter - > intr . num_intrs ;
for ( i = 0 ; i < adapter - > intr . num_intrs ; i + + ) {
buf [ j + + ] = VMXNET3_READ_BAR0_REG ( adapter , VMXNET3_REG_IMR
+ i * VMXNET3_REG_ALIGN ) ;
}
2011-01-14 17:59:47 +03:00
2015-09-22 06:01:29 +03:00
buf [ j + + ] = adapter - > num_tx_queues ;
for ( i = 0 ; i < adapter - > num_tx_queues ; i + + ) {
struct vmxnet3_tx_queue * tq = & adapter - > tx_queue [ i ] ;
buf [ j + + ] = VMXNET3_READ_BAR0_REG ( adapter , VMXNET3_REG_TXPROD +
i * VMXNET3_REG_ALIGN ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_LO ( tq - > tx_ring . basePA ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_HI ( tq - > tx_ring . basePA ) ;
buf [ j + + ] = tq - > tx_ring . size ;
buf [ j + + ] = tq - > tx_ring . next2fill ;
buf [ j + + ] = tq - > tx_ring . next2comp ;
buf [ j + + ] = tq - > tx_ring . gen ;
buf [ j + + ] = VMXNET3_GET_ADDR_LO ( tq - > data_ring . basePA ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_HI ( tq - > data_ring . basePA ) ;
buf [ j + + ] = tq - > data_ring . size ;
2016-06-16 20:51:55 +03:00
buf [ j + + ] = tq - > txdata_desc_size ;
2015-09-22 06:01:29 +03:00
buf [ j + + ] = VMXNET3_GET_ADDR_LO ( tq - > comp_ring . basePA ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_HI ( tq - > comp_ring . basePA ) ;
buf [ j + + ] = tq - > comp_ring . size ;
buf [ j + + ] = tq - > comp_ring . next2proc ;
buf [ j + + ] = tq - > comp_ring . gen ;
buf [ j + + ] = tq - > stopped ;
2011-01-14 17:59:47 +03:00
}
2015-09-22 06:01:29 +03:00
buf [ j + + ] = adapter - > num_rx_queues ;
2011-01-14 17:59:47 +03:00
for ( i = 0 ; i < adapter - > num_rx_queues ; i + + ) {
2015-09-22 06:01:29 +03:00
struct vmxnet3_rx_queue * rq = & adapter - > rx_queue [ i ] ;
buf [ j + + ] = VMXNET3_READ_BAR0_REG ( adapter , VMXNET3_REG_RXPROD +
i * VMXNET3_REG_ALIGN ) ;
buf [ j + + ] = VMXNET3_READ_BAR0_REG ( adapter , VMXNET3_REG_RXPROD2 +
i * VMXNET3_REG_ALIGN ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_LO ( rq - > rx_ring [ 0 ] . basePA ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_HI ( rq - > rx_ring [ 0 ] . basePA ) ;
buf [ j + + ] = rq - > rx_ring [ 0 ] . size ;
buf [ j + + ] = rq - > rx_ring [ 0 ] . next2fill ;
buf [ j + + ] = rq - > rx_ring [ 0 ] . next2comp ;
buf [ j + + ] = rq - > rx_ring [ 0 ] . gen ;
buf [ j + + ] = VMXNET3_GET_ADDR_LO ( rq - > rx_ring [ 1 ] . basePA ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_HI ( rq - > rx_ring [ 1 ] . basePA ) ;
buf [ j + + ] = rq - > rx_ring [ 1 ] . size ;
buf [ j + + ] = rq - > rx_ring [ 1 ] . next2fill ;
buf [ j + + ] = rq - > rx_ring [ 1 ] . next2comp ;
buf [ j + + ] = rq - > rx_ring [ 1 ] . gen ;
2016-06-16 20:51:56 +03:00
buf [ j + + ] = VMXNET3_GET_ADDR_LO ( rq - > data_ring . basePA ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_HI ( rq - > data_ring . basePA ) ;
buf [ j + + ] = rq - > rx_ring [ 0 ] . size ;
buf [ j + + ] = rq - > data_ring . desc_size ;
2011-01-14 17:59:47 +03:00
2015-09-22 06:01:29 +03:00
buf [ j + + ] = VMXNET3_GET_ADDR_LO ( rq - > comp_ring . basePA ) ;
buf [ j + + ] = VMXNET3_GET_ADDR_HI ( rq - > comp_ring . basePA ) ;
buf [ j + + ] = rq - > comp_ring . size ;
buf [ j + + ] = rq - > comp_ring . next2proc ;
buf [ j + + ] = rq - > comp_ring . gen ;
}
2009-10-13 11:15:51 +04:00
}
static void
vmxnet3_get_wol ( struct net_device * netdev , struct ethtool_wolinfo * wol )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
wol - > supported = WAKE_UCAST | WAKE_ARP | WAKE_MAGIC ;
wol - > wolopts = adapter - > wol ;
}
static int
vmxnet3_set_wol ( struct net_device * netdev , struct ethtool_wolinfo * wol )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
if ( wol - > wolopts & ( WAKE_PHY | WAKE_MCAST | WAKE_BCAST |
WAKE_MAGICSECURE ) ) {
return - EOPNOTSUPP ;
}
adapter - > wol = wol - > wolopts ;
device_set_wakeup_enable ( & adapter - > pdev - > dev , adapter - > wol ) ;
return 0 ;
}
static int
vmxnet3_get_settings ( struct net_device * netdev , struct ethtool_cmd * ecmd )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
ecmd - > supported = SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full |
SUPPORTED_TP ;
ecmd - > advertising = ADVERTISED_TP ;
ecmd - > port = PORT_TP ;
ecmd - > transceiver = XCVR_INTERNAL ;
if ( adapter - > link_speed ) {
2011-04-27 22:32:40 +04:00
ethtool_cmd_speed_set ( ecmd , adapter - > link_speed ) ;
2009-10-13 11:15:51 +04:00
ecmd - > duplex = DUPLEX_FULL ;
} else {
2014-06-06 16:17:00 +04:00
ethtool_cmd_speed_set ( ecmd , SPEED_UNKNOWN ) ;
ecmd - > duplex = DUPLEX_UNKNOWN ;
2009-10-13 11:15:51 +04:00
}
return 0 ;
}
static void
vmxnet3_get_ringparam ( struct net_device * netdev ,
struct ethtool_ringparam * param )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
param - > rx_max_pending = VMXNET3_RX_RING_MAX_SIZE ;
param - > tx_max_pending = VMXNET3_TX_RING_MAX_SIZE ;
2016-06-16 20:51:56 +03:00
param - > rx_mini_max_pending = VMXNET3_VERSION_GE_3 ( adapter ) ?
VMXNET3_RXDATA_DESC_MAX_SIZE : 0 ;
2015-01-06 20:20:15 +03:00
param - > rx_jumbo_max_pending = VMXNET3_RX_RING2_MAX_SIZE ;
2009-10-13 11:15:51 +04:00
2014-06-13 18:03:21 +04:00
param - > rx_pending = adapter - > rx_ring_size ;
param - > tx_pending = adapter - > tx_ring_size ;
2016-06-16 20:51:56 +03:00
param - > rx_mini_pending = VMXNET3_VERSION_GE_3 ( adapter ) ?
adapter - > rxdata_desc_size : 0 ;
2015-01-06 20:20:15 +03:00
param - > rx_jumbo_pending = adapter - > rx_ring2_size ;
2009-10-13 11:15:51 +04:00
}
static int
vmxnet3_set_ringparam ( struct net_device * netdev ,
struct ethtool_ringparam * param )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
2015-01-06 20:20:15 +03:00
u32 new_tx_ring_size , new_rx_ring_size , new_rx_ring2_size ;
2016-06-16 20:51:56 +03:00
u16 new_rxdata_desc_size ;
2009-10-13 11:15:51 +04:00
u32 sz ;
int err = 0 ;
if ( param - > tx_pending = = 0 | | param - > tx_pending >
VMXNET3_TX_RING_MAX_SIZE )
return - EINVAL ;
if ( param - > rx_pending = = 0 | | param - > rx_pending >
VMXNET3_RX_RING_MAX_SIZE )
return - EINVAL ;
2015-01-06 20:20:15 +03:00
if ( param - > rx_jumbo_pending = = 0 | |
param - > rx_jumbo_pending > VMXNET3_RX_RING2_MAX_SIZE )
return - EINVAL ;
2013-03-06 16:04:53 +04:00
/* if adapter not yet initialized, do nothing */
if ( adapter - > rx_buf_per_pkt = = 0 ) {
netdev_err ( netdev , " adapter not completely initialized, "
" ring size cannot be changed yet \n " ) ;
return - EOPNOTSUPP ;
}
2009-10-13 11:15:51 +04:00
2016-06-16 20:51:56 +03:00
if ( VMXNET3_VERSION_GE_3 ( adapter ) ) {
if ( param - > rx_mini_pending < 0 | |
param - > rx_mini_pending > VMXNET3_RXDATA_DESC_MAX_SIZE ) {
return - EINVAL ;
}
} else if ( param - > rx_mini_pending ! = 0 ) {
return - EINVAL ;
}
2009-10-13 11:15:51 +04:00
/* round it up to a multiple of VMXNET3_RING_SIZE_ALIGN */
new_tx_ring_size = ( param - > tx_pending + VMXNET3_RING_SIZE_MASK ) &
~ VMXNET3_RING_SIZE_MASK ;
new_tx_ring_size = min_t ( u32 , new_tx_ring_size ,
VMXNET3_TX_RING_MAX_SIZE ) ;
if ( new_tx_ring_size > VMXNET3_TX_RING_MAX_SIZE | | ( new_tx_ring_size %
VMXNET3_RING_SIZE_ALIGN ) ! = 0 )
return - EINVAL ;
/* ring0 has to be a multiple of
* rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN
*/
sz = adapter - > rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN ;
new_rx_ring_size = ( param - > rx_pending + sz - 1 ) / sz * sz ;
new_rx_ring_size = min_t ( u32 , new_rx_ring_size ,
VMXNET3_RX_RING_MAX_SIZE / sz * sz ) ;
if ( new_rx_ring_size > VMXNET3_RX_RING_MAX_SIZE | | ( new_rx_ring_size %
sz ) ! = 0 )
return - EINVAL ;
2015-01-06 20:20:15 +03:00
/* ring2 has to be a multiple of VMXNET3_RING_SIZE_ALIGN */
new_rx_ring2_size = ( param - > rx_jumbo_pending + VMXNET3_RING_SIZE_MASK ) &
~ VMXNET3_RING_SIZE_MASK ;
new_rx_ring2_size = min_t ( u32 , new_rx_ring2_size ,
VMXNET3_RX_RING2_MAX_SIZE ) ;
2016-06-16 20:51:56 +03:00
/* rx data ring buffer size has to be a multiple of
* VMXNET3_RXDATA_DESC_SIZE_ALIGN
*/
new_rxdata_desc_size =
( param - > rx_mini_pending + VMXNET3_RXDATA_DESC_SIZE_MASK ) &
~ VMXNET3_RXDATA_DESC_SIZE_MASK ;
new_rxdata_desc_size = min_t ( u16 , new_rxdata_desc_size ,
VMXNET3_RXDATA_DESC_MAX_SIZE ) ;
2015-01-06 20:20:15 +03:00
if ( new_tx_ring_size = = adapter - > tx_ring_size & &
new_rx_ring_size = = adapter - > rx_ring_size & &
2016-06-16 20:51:56 +03:00
new_rx_ring2_size = = adapter - > rx_ring2_size & &
new_rxdata_desc_size = = adapter - > rxdata_desc_size ) {
2009-10-13 11:15:51 +04:00
return 0 ;
}
/*
* Reset_work may be in the middle of resetting the device , wait for its
* completion .
*/
while ( test_and_set_bit ( VMXNET3_STATE_BIT_RESETTING , & adapter - > state ) )
msleep ( 1 ) ;
if ( netif_running ( netdev ) ) {
vmxnet3_quiesce_dev ( adapter ) ;
vmxnet3_reset_dev ( adapter ) ;
/* recreate the rx queue and the tx queue based on the
* new sizes */
2010-11-19 13:55:24 +03:00
vmxnet3_tq_destroy_all ( adapter ) ;
vmxnet3_rq_destroy_all ( adapter ) ;
2009-10-13 11:15:51 +04:00
err = vmxnet3_create_queues ( adapter , new_tx_ring_size ,
2016-06-16 20:51:55 +03:00
new_rx_ring_size , new_rx_ring2_size ,
2016-06-16 20:51:56 +03:00
adapter - > txdata_desc_size ,
new_rxdata_desc_size ) ;
2009-10-13 11:15:51 +04:00
if ( err ) {
/* failed, most likely because of OOM, try default
* size */
2013-01-15 11:28:30 +04:00
netdev_err ( netdev , " failed to apply new sizes, "
" try the default ones \n " ) ;
2014-06-13 18:03:21 +04:00
new_rx_ring_size = VMXNET3_DEF_RX_RING_SIZE ;
2015-01-06 20:20:15 +03:00
new_rx_ring2_size = VMXNET3_DEF_RX_RING2_SIZE ;
2014-06-13 18:03:21 +04:00
new_tx_ring_size = VMXNET3_DEF_TX_RING_SIZE ;
2016-06-16 20:51:56 +03:00
new_rxdata_desc_size = VMXNET3_VERSION_GE_3 ( adapter ) ?
VMXNET3_DEF_RXDATA_DESC_SIZE : 0 ;
2009-10-13 11:15:51 +04:00
err = vmxnet3_create_queues ( adapter ,
2014-06-13 18:03:21 +04:00
new_tx_ring_size ,
new_rx_ring_size ,
2016-06-16 20:51:55 +03:00
new_rx_ring2_size ,
2016-06-16 20:51:56 +03:00
adapter - > txdata_desc_size ,
new_rxdata_desc_size ) ;
2009-10-13 11:15:51 +04:00
if ( err ) {
2013-01-15 11:28:30 +04:00
netdev_err ( netdev , " failed to create queues "
" with default sizes. Closing it \n " ) ;
2009-10-13 11:15:51 +04:00
goto out ;
}
}
err = vmxnet3_activate_dev ( adapter ) ;
if ( err )
2013-01-15 11:28:30 +04:00
netdev_err ( netdev , " failed to re-activate, error %d. "
" Closing it \n " , err ) ;
2009-10-13 11:15:51 +04:00
}
2014-06-13 18:03:21 +04:00
adapter - > tx_ring_size = new_tx_ring_size ;
adapter - > rx_ring_size = new_rx_ring_size ;
2015-01-06 20:20:15 +03:00
adapter - > rx_ring2_size = new_rx_ring2_size ;
2016-06-16 20:51:56 +03:00
adapter - > rxdata_desc_size = new_rxdata_desc_size ;
2009-10-13 11:15:51 +04:00
out :
clear_bit ( VMXNET3_STATE_BIT_RESETTING , & adapter - > state ) ;
if ( err )
vmxnet3_force_close ( adapter ) ;
return err ;
}
2010-11-19 13:55:24 +03:00
static int
vmxnet3_get_rxnfc ( struct net_device * netdev , struct ethtool_rxnfc * info ,
2011-09-06 17:49:12 +04:00
u32 * rules )
2010-11-19 13:55:24 +03:00
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
switch ( info - > cmd ) {
case ETHTOOL_GRXRINGS :
info - > data = adapter - > num_rx_queues ;
return 0 ;
}
return - EOPNOTSUPP ;
}
2010-11-27 13:33:55 +03:00
# ifdef VMXNET3_RSS
2011-12-15 17:55:01 +04:00
static u32
vmxnet3_get_rss_indir_size ( struct net_device * netdev )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
struct UPT1_RSSConf * rssConf = adapter - > rss_conf ;
return rssConf - > indTableSize ;
}
2010-11-19 13:55:24 +03:00
static int
2014-12-02 19:12:10 +03:00
vmxnet3_get_rss ( struct net_device * netdev , u32 * p , u8 * key , u8 * hfunc )
2010-11-19 13:55:24 +03:00
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
struct UPT1_RSSConf * rssConf = adapter - > rss_conf ;
2011-12-15 17:55:01 +04:00
unsigned int n = rssConf - > indTableSize ;
2010-11-19 13:55:24 +03:00
2014-12-02 19:12:10 +03:00
if ( hfunc )
* hfunc = ETH_RSS_HASH_TOP ;
if ( ! p )
return 0 ;
2010-11-19 13:55:24 +03:00
while ( n - - )
2011-12-15 17:55:01 +04:00
p [ n ] = rssConf - > indTable [ n ] ;
2010-11-19 13:55:24 +03:00
return 0 ;
}
static int
2014-12-02 19:12:10 +03:00
vmxnet3_set_rss ( struct net_device * netdev , const u32 * p , const u8 * key ,
const u8 hfunc )
2010-11-19 13:55:24 +03:00
{
unsigned int i ;
2011-01-14 17:59:57 +03:00
unsigned long flags ;
2010-11-19 13:55:24 +03:00
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
struct UPT1_RSSConf * rssConf = adapter - > rss_conf ;
2014-12-02 19:12:10 +03:00
/* We do not allow change in unsupported parameters */
if ( key | |
( hfunc ! = ETH_RSS_HASH_NO_CHANGE & & hfunc ! = ETH_RSS_HASH_TOP ) )
return - EOPNOTSUPP ;
if ( ! p )
return 0 ;
2010-11-19 13:55:24 +03:00
for ( i = 0 ; i < rssConf - > indTableSize ; i + + )
2011-12-15 17:55:01 +04:00
rssConf - > indTable [ i ] = p [ i ] ;
2010-11-19 13:55:24 +03:00
2011-01-14 17:59:57 +03:00
spin_lock_irqsave ( & adapter - > cmd_lock , flags ) ;
2010-11-19 13:55:24 +03:00
VMXNET3_WRITE_BAR1_REG ( adapter , VMXNET3_REG_CMD ,
VMXNET3_CMD_UPDATE_RSSIDT ) ;
2011-01-14 17:59:57 +03:00
spin_unlock_irqrestore ( & adapter - > cmd_lock , flags ) ;
2010-11-19 13:55:24 +03:00
return 0 ;
}
2010-11-27 13:33:55 +03:00
# endif
2010-11-19 13:55:24 +03:00
2016-06-16 20:51:57 +03:00
static int
vmxnet3_get_coalesce ( struct net_device * netdev , struct ethtool_coalesce * ec )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
if ( ! VMXNET3_VERSION_GE_3 ( adapter ) )
return - EOPNOTSUPP ;
switch ( adapter - > coal_conf - > coalMode ) {
case VMXNET3_COALESCE_DISABLED :
/* struct ethtool_coalesce is already initialized to 0 */
break ;
case VMXNET3_COALESCE_ADAPT :
ec - > use_adaptive_rx_coalesce = true ;
break ;
case VMXNET3_COALESCE_STATIC :
ec - > tx_max_coalesced_frames =
adapter - > coal_conf - > coalPara . coalStatic . tx_comp_depth ;
ec - > rx_max_coalesced_frames =
adapter - > coal_conf - > coalPara . coalStatic . rx_depth ;
break ;
case VMXNET3_COALESCE_RBC : {
u32 rbc_rate ;
rbc_rate = adapter - > coal_conf - > coalPara . coalRbc . rbc_rate ;
ec - > rx_coalesce_usecs = VMXNET3_COAL_RBC_USECS ( rbc_rate ) ;
}
break ;
default :
return - EOPNOTSUPP ;
}
return 0 ;
}
static int
vmxnet3_set_coalesce ( struct net_device * netdev , struct ethtool_coalesce * ec )
{
struct vmxnet3_adapter * adapter = netdev_priv ( netdev ) ;
struct Vmxnet3_DriverShared * shared = adapter - > shared ;
union Vmxnet3_CmdInfo * cmdInfo = & shared - > cu . cmdInfo ;
unsigned long flags ;
if ( ! VMXNET3_VERSION_GE_3 ( adapter ) )
return - EOPNOTSUPP ;
if ( ec - > rx_coalesce_usecs_irq | |
ec - > rx_max_coalesced_frames_irq | |
ec - > tx_coalesce_usecs | |
ec - > tx_coalesce_usecs_irq | |
ec - > tx_max_coalesced_frames_irq | |
ec - > stats_block_coalesce_usecs | |
ec - > use_adaptive_tx_coalesce | |
ec - > pkt_rate_low | |
ec - > rx_coalesce_usecs_low | |
ec - > rx_max_coalesced_frames_low | |
ec - > tx_coalesce_usecs_low | |
ec - > tx_max_coalesced_frames_low | |
ec - > pkt_rate_high | |
ec - > rx_coalesce_usecs_high | |
ec - > rx_max_coalesced_frames_high | |
ec - > tx_coalesce_usecs_high | |
ec - > tx_max_coalesced_frames_high | |
ec - > rate_sample_interval ) {
return - EINVAL ;
}
if ( ( ec - > rx_coalesce_usecs = = 0 ) & &
( ec - > use_adaptive_rx_coalesce = = 0 ) & &
( ec - > tx_max_coalesced_frames = = 0 ) & &
( ec - > rx_max_coalesced_frames = = 0 ) ) {
memset ( adapter - > coal_conf , 0 , sizeof ( * adapter - > coal_conf ) ) ;
adapter - > coal_conf - > coalMode = VMXNET3_COALESCE_DISABLED ;
goto done ;
}
if ( ec - > rx_coalesce_usecs ! = 0 ) {
u32 rbc_rate ;
if ( ( ec - > use_adaptive_rx_coalesce ! = 0 ) | |
( ec - > tx_max_coalesced_frames ! = 0 ) | |
( ec - > rx_max_coalesced_frames ! = 0 ) ) {
return - EINVAL ;
}
rbc_rate = VMXNET3_COAL_RBC_RATE ( ec - > rx_coalesce_usecs ) ;
if ( rbc_rate < VMXNET3_COAL_RBC_MIN_RATE | |
rbc_rate > VMXNET3_COAL_RBC_MAX_RATE ) {
return - EINVAL ;
}
memset ( adapter - > coal_conf , 0 , sizeof ( * adapter - > coal_conf ) ) ;
adapter - > coal_conf - > coalMode = VMXNET3_COALESCE_RBC ;
adapter - > coal_conf - > coalPara . coalRbc . rbc_rate = rbc_rate ;
goto done ;
}
if ( ec - > use_adaptive_rx_coalesce ! = 0 ) {
if ( ( ec - > rx_coalesce_usecs ! = 0 ) | |
( ec - > tx_max_coalesced_frames ! = 0 ) | |
( ec - > rx_max_coalesced_frames ! = 0 ) ) {
return - EINVAL ;
}
memset ( adapter - > coal_conf , 0 , sizeof ( * adapter - > coal_conf ) ) ;
adapter - > coal_conf - > coalMode = VMXNET3_COALESCE_ADAPT ;
goto done ;
}
if ( ( ec - > tx_max_coalesced_frames ! = 0 ) | |
( ec - > rx_max_coalesced_frames ! = 0 ) ) {
if ( ( ec - > rx_coalesce_usecs ! = 0 ) | |
( ec - > use_adaptive_rx_coalesce ! = 0 ) ) {
return - EINVAL ;
}
if ( ( ec - > tx_max_coalesced_frames >
VMXNET3_COAL_STATIC_MAX_DEPTH ) | |
( ec - > rx_max_coalesced_frames >
VMXNET3_COAL_STATIC_MAX_DEPTH ) ) {
return - EINVAL ;
}
memset ( adapter - > coal_conf , 0 , sizeof ( * adapter - > coal_conf ) ) ;
adapter - > coal_conf - > coalMode = VMXNET3_COALESCE_STATIC ;
adapter - > coal_conf - > coalPara . coalStatic . tx_comp_depth =
( ec - > tx_max_coalesced_frames ?
ec - > tx_max_coalesced_frames :
VMXNET3_COAL_STATIC_DEFAULT_DEPTH ) ;
adapter - > coal_conf - > coalPara . coalStatic . rx_depth =
( ec - > rx_max_coalesced_frames ?
ec - > rx_max_coalesced_frames :
VMXNET3_COAL_STATIC_DEFAULT_DEPTH ) ;
adapter - > coal_conf - > coalPara . coalStatic . tx_depth =
VMXNET3_COAL_STATIC_DEFAULT_DEPTH ;
goto done ;
}
done :
adapter - > default_coal_mode = false ;
if ( netif_running ( netdev ) ) {
spin_lock_irqsave ( & adapter - > cmd_lock , flags ) ;
cmdInfo - > varConf . confVer = 1 ;
cmdInfo - > varConf . confLen =
cpu_to_le32 ( sizeof ( * adapter - > coal_conf ) ) ;
cmdInfo - > varConf . confPA = cpu_to_le64 ( adapter - > coal_conf_pa ) ;
VMXNET3_WRITE_BAR1_REG ( adapter , VMXNET3_REG_CMD ,
VMXNET3_CMD_SET_COALESCE ) ;
spin_unlock_irqrestore ( & adapter - > cmd_lock , flags ) ;
}
return 0 ;
}
2012-01-04 15:58:13 +04:00
static const struct ethtool_ops vmxnet3_ethtool_ops = {
2009-10-13 11:15:51 +04:00
. get_settings = vmxnet3_get_settings ,
. get_drvinfo = vmxnet3_get_drvinfo ,
. get_regs_len = vmxnet3_get_regs_len ,
. get_regs = vmxnet3_get_regs ,
. get_wol = vmxnet3_get_wol ,
. set_wol = vmxnet3_set_wol ,
. get_link = ethtool_op_get_link ,
2016-06-16 20:51:57 +03:00
. get_coalesce = vmxnet3_get_coalesce ,
. set_coalesce = vmxnet3_set_coalesce ,
2009-10-13 11:15:51 +04:00
. get_strings = vmxnet3_get_strings ,
. get_sset_count = vmxnet3_get_sset_count ,
. get_ethtool_stats = vmxnet3_get_ethtool_stats ,
. get_ringparam = vmxnet3_get_ringparam ,
. set_ringparam = vmxnet3_set_ringparam ,
2010-11-19 13:55:24 +03:00
. get_rxnfc = vmxnet3_get_rxnfc ,
2010-11-27 13:33:55 +03:00
# ifdef VMXNET3_RSS
2011-12-15 17:55:01 +04:00
. get_rxfh_indir_size = vmxnet3_get_rss_indir_size ,
2014-05-15 04:25:27 +04:00
. get_rxfh = vmxnet3_get_rss ,
. set_rxfh = vmxnet3_set_rss ,
2010-11-27 13:33:55 +03:00
# endif
2009-10-13 11:15:51 +04:00
} ;
void vmxnet3_set_ethtool_ops ( struct net_device * netdev )
{
2014-05-11 04:12:32 +04:00
netdev - > ethtool_ops = & vmxnet3_ethtool_ops ;
2009-10-13 11:15:51 +04:00
}