blob: df2841545733ed90909027801ee5aebd7dd1f1ca [file] [log] [blame]
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
This software file (the "File") is owned and distributed by Marvell
International Ltd. and/or its affiliates ("Marvell") under the following
alternative licensing terms. Once you have made an election to distribute the
File under one of the following license alternatives, please (i) delete this
introductory statement regarding license alternatives, (ii) delete the two
license alternatives that you have not elected to use and (iii) preserve the
Marvell copyright notice above.
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
*******************************************************************************/
#include "mvCommon.h"
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <linux/mii.h>
#include "mvOs.h"
#include "mvDebug.h"
#include "dbg-trace.h"
#include "mvSysHwConfig.h"
#include "boardEnv/mvBoardEnvLib.h"
#include "ctrlEnv/mvCtrlEnvLib.h"
#include "eth-phy/mvEthPhy.h"
#include "mvSysEthPhyApi.h"
#include "mvSysNetaApi.h"
#include "gbe/mvNeta.h"
#include "bm/mvBm.h"
#include "pnc/mvPnc.h"
#include "mv_switch.h"
#include "mv_netdev.h"
#include "mv_eth_tool.h"
#include "mvOs.h"
#include "mvSysHwConfig.h"
#define MV_ETH_TOOL_AN_TIMEOUT 5000
static int isSwitch(struct eth_port *priv)
{
return (priv->flags & (MV_ETH_F_SWITCH | MV_ETH_F_EXT_SWITCH));
}
/******************************************************************************
* mv_eth_tool_restore_settings
* Description:
* restore saved speed/dublex/an settings
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* None
* RETURN:
* 0 for success
*
*******************************************************************************/
int mv_eth_tool_restore_settings(struct net_device *netdev)
{
struct eth_port *priv = MV_ETH_PRIV(netdev);
int mv_phy_speed, mv_phy_duplex;
MV_U32 mv_phy_addr = mvBoardPhyAddrGet(priv->port);
MV_ETH_PORT_SPEED mv_mac_speed;
MV_ETH_PORT_DUPLEX mv_mac_duplex;
int err = -EINVAL;
if ((priv == NULL) || (isSwitch(priv)))
return -EOPNOTSUPP;
switch (priv->speed_cfg) {
case SPEED_10:
mv_phy_speed = 0;
mv_mac_speed = MV_ETH_SPEED_10;
break;
case SPEED_100:
mv_phy_speed = 1;
mv_mac_speed = MV_ETH_SPEED_100;
break;
case SPEED_1000:
mv_phy_speed = 2;
mv_mac_speed = MV_ETH_SPEED_1000;
break;
default:
return -EINVAL;
}
switch (priv->duplex_cfg) {
case DUPLEX_HALF:
mv_phy_duplex = 0;
mv_mac_duplex = MV_ETH_DUPLEX_HALF;
break;
case DUPLEX_FULL:
mv_phy_duplex = 1;
mv_mac_duplex = MV_ETH_DUPLEX_FULL;
break;
default:
return -EINVAL;
}
if (priv->autoneg_cfg == AUTONEG_ENABLE) {
err = mvNetaSpeedDuplexSet(priv->port, MV_ETH_SPEED_AN, MV_ETH_DUPLEX_AN);
if (!err)
err = mvEthPhyAdvertiseSet(mv_phy_addr, priv->advertise_cfg);
/* Restart AN on PHY enables it */
if (!err) {
err = mvEthPhyRestartAN(mv_phy_addr, MV_ETH_TOOL_AN_TIMEOUT);
if (err == MV_TIMEOUT) {
MV_ETH_PORT_STATUS ps;
mvNetaLinkStatus(priv->port, &ps);
if (!ps.linkup)
err = 0;
}
}
} else if (priv->autoneg_cfg == AUTONEG_DISABLE) {
err = mvEthPhyDisableAN(mv_phy_addr, mv_phy_speed, mv_phy_duplex);
if (!err)
err = mvNetaSpeedDuplexSet(priv->port, mv_mac_speed, mv_mac_duplex);
} else {
err = -EINVAL;
}
return err;
}
/******************************************************************************
* mv_eth_tool_get_settings
* Description:
* ethtool get standard port settings
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* cmd command (settings)
* RETURN:
* 0 for success
*
*******************************************************************************/
int mv_eth_tool_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{
struct eth_port *priv = MV_ETH_PRIV(netdev);
u16 lp_ad, stat1000;
MV_U32 mv_phy_addr;
MV_ETH_PORT_SPEED speed;
MV_ETH_PORT_DUPLEX duplex;
MV_ETH_PORT_STATUS status;
if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
return -EOPNOTSUPP;
}
cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII
| SUPPORTED_1000baseT_Full);
mv_phy_addr = mvBoardPhyAddrGet(priv->port);
mvNetaLinkStatus(priv->port, &status);
switch (status.speed) {
case MV_ETH_SPEED_1000:
cmd->speed = SPEED_1000;
break;
case MV_ETH_SPEED_100:
cmd->speed = SPEED_100;
break;
case MV_ETH_SPEED_10:
cmd->speed = SPEED_10;
break;
default:
return -EINVAL;
}
if (status.duplex == MV_ETH_DUPLEX_FULL)
cmd->duplex = 1;
else
cmd->duplex = 0;
cmd->port = PORT_MII;
cmd->phy_address = mv_phy_addr;
cmd->transceiver = XCVR_INTERNAL;
/* check if speed and duplex are AN */
mvNetaSpeedDuplexGet(priv->port, &speed, &duplex);
if (speed == MV_ETH_SPEED_AN && duplex == MV_ETH_DUPLEX_AN) {
cmd->lp_advertising = cmd->advertising = 0;
cmd->autoneg = AUTONEG_ENABLE;
mvEthPhyAdvertiseGet(mv_phy_addr, (MV_U16 *)&(cmd->advertising));
mvEthPhyRegRead(mv_phy_addr, MII_LPA, &lp_ad);
if (lp_ad & LPA_LPACK)
cmd->lp_advertising |= ADVERTISED_Autoneg;
if (lp_ad & ADVERTISE_10HALF)
cmd->lp_advertising |= ADVERTISED_10baseT_Half;
if (lp_ad & ADVERTISE_10FULL)
cmd->lp_advertising |= ADVERTISED_10baseT_Full;
if (lp_ad & ADVERTISE_100HALF)
cmd->lp_advertising |= ADVERTISED_100baseT_Half;
if (lp_ad & ADVERTISE_100FULL)
cmd->lp_advertising |= ADVERTISED_100baseT_Full;
mvEthPhyRegRead(mv_phy_addr, MII_STAT1000, &stat1000);
if (stat1000 & LPA_1000HALF)
cmd->lp_advertising |= ADVERTISED_1000baseT_Half;
if (stat1000 & LPA_1000FULL)
cmd->lp_advertising |= ADVERTISED_1000baseT_Full;
} else
cmd->autoneg = AUTONEG_DISABLE;
return 0;
}
/******************************************************************************
* mv_eth_tool_set_settings
* Description:
* ethtool set standard port settings
* INPUT:
* netdev Network device structure pointer
* cmd command (settings)
* OUTPUT
* None
* RETURN:
* 0 for success
*
*******************************************************************************/
int mv_eth_tool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct eth_port *priv = MV_ETH_PRIV(dev);
int _speed, _duplex, _autoneg, _advertise, err;
if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
printk(KERN_ERR "%s is not supported on %s\n", __func__, dev->name);
return -EOPNOTSUPP;
}
_duplex = priv->duplex_cfg;
_speed = priv->speed_cfg;
_autoneg = priv->autoneg_cfg;
_advertise = priv->advertise_cfg;
priv->duplex_cfg = cmd->duplex;
priv->speed_cfg = cmd->speed;
priv->autoneg_cfg = cmd->autoneg;
priv->advertise_cfg = cmd->advertising;
err = mv_eth_tool_restore_settings(dev);
if (err) {
priv->duplex_cfg = _duplex;
priv->speed_cfg = _speed;
priv->autoneg_cfg = _autoneg;
priv->advertise_cfg = _advertise;
}
return err;
}
/******************************************************************************
* mv_eth_tool_get_regs_len
* Description:
* ethtool get registers array length
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* None
* RETURN:
* registers array length
*
*******************************************************************************/
int mv_eth_tool_get_regs_len(struct net_device *netdev)
{
#define MV_ETH_TOOL_REGS_LEN 32
return (MV_ETH_TOOL_REGS_LEN * sizeof(uint32_t));
}
/******************************************************************************
* mv_eth_tool_get_drvinfo
* Description:
* ethtool get driver information
* INPUT:
* netdev Network device structure pointer
* info driver information
* OUTPUT
* info driver information
* RETURN:
* None
*
*******************************************************************************/
void mv_eth_tool_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
{
strcpy(info->driver, "mv_eth");
/*strcpy(info->version, LSP_VERSION);*/
strcpy(info->fw_version, "N/A");
strcpy(info->bus_info, "Mbus");
/* TBD
info->n_stats = MV_ETH_TOOL_STATS_LEN;
*/
info->testinfo_len = 0;
info->regdump_len = mv_eth_tool_get_regs_len(netdev);
info->eedump_len = 0;
}
/******************************************************************************
* mv_eth_tool_get_regs
* Description:
* ethtool get registers array
* INPUT:
* netdev Network device structure pointer
* regs registers information
* OUTPUT
* p registers array
* RETURN:
* None
*
*******************************************************************************/
void mv_eth_tool_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
struct eth_port *priv = MV_ETH_PRIV(netdev);
uint32_t *regs_buff = p;
if ((priv == NULL) || MV_PON_PORT(priv->port)) {
printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
return;
}
memset(p, 0, MV_ETH_TOOL_REGS_LEN * sizeof(uint32_t));
regs->version = mvCtrlModelRevGet();
/* ETH port registers */
regs_buff[0] = MV_REG_READ(ETH_PORT_STATUS_REG(priv->port));
regs_buff[1] = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(priv->port));
regs_buff[2] = MV_REG_READ(ETH_PORT_CONFIG_REG(priv->port));
regs_buff[3] = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(priv->port));
regs_buff[4] = MV_REG_READ(ETH_SDMA_CONFIG_REG(priv->port));
/* regs_buff[5] = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(priv->port)); */
regs_buff[6] = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(priv->port));
/* regs_buff[7] = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(priv->port)); */
regs_buff[8] = MV_REG_READ(ETH_INTR_CAUSE_REG(priv->port));
regs_buff[9] = MV_REG_READ(ETH_INTR_CAUSE_EXT_REG(priv->port));
regs_buff[10] = MV_REG_READ(ETH_INTR_MASK_REG(priv->port));
regs_buff[11] = MV_REG_READ(ETH_INTR_MASK_EXT_REG(priv->port));
/* ETH Unit registers */
regs_buff[16] = MV_REG_READ(ETH_PHY_ADDR_REG(priv->port));
regs_buff[17] = MV_REG_READ(ETH_UNIT_INTR_CAUSE_REG(priv->port));
regs_buff[18] = MV_REG_READ(ETH_UNIT_INTR_MASK_REG(priv->port));
regs_buff[19] = MV_REG_READ(ETH_UNIT_ERROR_ADDR_REG(priv->port));
regs_buff[20] = MV_REG_READ(ETH_UNIT_INT_ADDR_ERROR_REG(priv->port));
}
/******************************************************************************
* mv_eth_tool_nway_reset
* Description:
* ethtool restart auto negotiation
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* None
* RETURN:
* 0 on success
*
*******************************************************************************/
int mv_eth_tool_nway_reset(struct net_device *netdev)
{
struct eth_port *priv = MV_ETH_PRIV(netdev);
MV_U32 phy_addr;
if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
printk(KERN_ERR "interface %s is not supported\n", netdev->name);
return -EOPNOTSUPP;
}
phy_addr = mvBoardPhyAddrGet(priv->port);
if (mvEthPhyRestartAN(phy_addr, MV_ETH_TOOL_AN_TIMEOUT) != MV_OK)
return -EINVAL;
return 0;
}
/******************************************************************************
* mv_eth_tool_get_link
* Description:
* ethtool get link status
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* None
* RETURN:
* 0 if link is down, 1 if link is up
*
*******************************************************************************/
u32 mv_eth_tool_get_link(struct net_device *netdev)
{
struct eth_port *pp = MV_ETH_PRIV(netdev);
struct eth_netdev *dev_priv = MV_DEV_PRIV(netdev);
if (pp == NULL) {
printk(KERN_ERR "interface %s is not supported\n", netdev->name);
return -EOPNOTSUPP;
}
if (isSwitch(pp)) {
if (dev_priv == NULL)
return -EOPNOTSUPP;
return (dev_priv->link_map != 0);
}
#ifdef CONFIG_MV_PON
if (MV_PON_PORT(pp->port))
return mv_pon_link_status();
#endif /* CONFIG_MV_PON */
return mvNetaLinkIsUp(pp->port);
}
/******************************************************************************
* mv_eth_tool_get_coalesce
* Description:
* ethtool get RX/TX coalesce parameters
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* cmd Coalesce parameters
* RETURN:
* 0 on success
*
*******************************************************************************/
int mv_eth_tool_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *cmd)
{
struct eth_port *pp = MV_ETH_PRIV(netdev);
/* get coal parameters only for rxq=0, txp=txq=0 !!!
notice that if you use ethtool to set coal, then all queues have the same value */
cmd->rx_coalesce_usecs = mvNetaRxqTimeCoalGet(pp->port, 0);
cmd->rx_max_coalesced_frames = mvNetaRxqPktsCoalGet(pp->port, 0);
cmd->tx_max_coalesced_frames = mvNetaTxDonePktsCoalGet(pp->port, 0, 0);
return 0;
}
/******************************************************************************
* mv_eth_tool_set_coalesce
* Description:
* ethtool set RX/TX coalesce parameters
* INPUT:
* netdev Network device structure pointer
* cmd Coalesce parameters
* OUTPUT
* None
* RETURN:
* 0 on success
*
*******************************************************************************/
int mv_eth_tool_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *cmd)
{
struct eth_port *pp = MV_ETH_PRIV(netdev);
int rxq, txp, txq;
/* can't set rx coalesce with both 0 pkts and 0 usecs, tx coalesce supports only pkts */
if ((!cmd->rx_coalesce_usecs && !cmd->rx_max_coalesced_frames) || (!cmd->tx_max_coalesced_frames))
return -EPERM;
for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
mv_eth_rx_ptks_coal_set(pp->port, rxq, cmd->rx_max_coalesced_frames);
mv_eth_rx_time_coal_set(pp->port, rxq, cmd->rx_coalesce_usecs);
}
for (txp = 0; txp < pp->txp_num; txp++)
for (txq = 0; txq < CONFIG_MV_ETH_TXQ; txq++)
mv_eth_tx_done_ptks_coal_set(pp->port, txp, txq, cmd->tx_max_coalesced_frames);
return 0;
}
/******************************************************************************
* mv_eth_tool_get_ringparam
* Description:
* ethtool get ring parameters
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* ring Ring paranmeters
* RETURN:
* None
*
*******************************************************************************/
void mv_eth_tool_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
/* printk("in %s \n",__FUNCTION__); */
}
/******************************************************************************
* mv_eth_tool_get_pauseparam
* Description:
* ethtool get pause parameters
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* pause Pause paranmeters
* RETURN:
* None
*
*******************************************************************************/
void mv_eth_tool_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct eth_port *priv = MV_ETH_PRIV(netdev);
int port = priv->port;
MV_ETH_PORT_STATUS portStatus;
MV_ETH_PORT_FC flowCtrl;
if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
return;
}
mvNetaFlowCtrlGet(port, &flowCtrl);
if ((flowCtrl == MV_ETH_FC_AN_NO) || (flowCtrl == MV_ETH_FC_AN_SYM) || (flowCtrl == MV_ETH_FC_AN_ASYM))
pause->autoneg = AUTONEG_ENABLE;
else
pause->autoneg = AUTONEG_DISABLE;
mvNetaLinkStatus(port, &portStatus);
if (portStatus.rxFc == MV_ETH_FC_DISABLE)
pause->rx_pause = 0;
else
pause->rx_pause = 1;
if (portStatus.txFc == MV_ETH_FC_DISABLE)
pause->tx_pause = 0;
else
pause->tx_pause = 1;
}
/******************************************************************************
* mv_eth_tool_set_pauseparam
* Description:
* ethtool configure pause parameters
* INPUT:
* netdev Network device structure pointer
* pause Pause paranmeters
* OUTPUT
* None
* RETURN:
* 0 on success
*
*******************************************************************************/
int mv_eth_tool_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct eth_port *priv = MV_ETH_PRIV(netdev);
int port = priv->port;
MV_U32 phy_addr;
MV_STATUS status = MV_FAIL;
if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
return -EOPNOTSUPP;
}
if (pause->rx_pause && pause->tx_pause) { /* Enable FC */
if (pause->autoneg) { /* autoneg enable */
status = mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_SYM);
} else { /* autoneg disable */
status = mvNetaFlowCtrlSet(port, MV_ETH_FC_ENABLE);
}
} else if (!pause->rx_pause && !pause->tx_pause) { /* Disable FC */
if (pause->autoneg) { /* autoneg enable */
status = mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_NO);
} else { /* autoneg disable */
status = mvNetaFlowCtrlSet(port, MV_ETH_FC_DISABLE);
}
}
/* Only symmetric change for RX and TX flow control is allowed */
if (status == MV_OK) {
phy_addr = mvBoardPhyAddrGet(priv->port);
status = mvEthPhyRestartAN(phy_addr, MV_ETH_TOOL_AN_TIMEOUT);
}
if (status != MV_OK)
return -EINVAL;
return 0;
}
/******************************************************************************
* mv_eth_tool_get_rx_csum
* Description:
* ethtool get RX checksum offloading status
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* None
* RETURN:
* RX checksum
*
*******************************************************************************/
u32 mv_eth_tool_get_rx_csum(struct net_device *netdev)
{
#ifdef CONFIG_MV_ETH_RX_CSUM_OFFLOAD
struct eth_port *priv = MV_ETH_PRIV(netdev);
return (priv->rx_csum_offload != 0);
#else
return 0;
#endif
}
/******************************************************************************
* mv_eth_tool_set_rx_csum
* Description:
* ethtool enable/disable RX checksum offloading
* INPUT:
* netdev Network device structure pointer
* data Command data
* OUTPUT
* None
* RETURN:
* 0 on success
*
*******************************************************************************/
int mv_eth_tool_set_rx_csum(struct net_device *netdev, uint32_t data)
{
#ifdef CONFIG_MV_ETH_RX_CSUM_OFFLOAD
struct eth_port *priv = MV_ETH_PRIV(netdev);
priv->rx_csum_offload = data;
return 0;
#else
return -EOPNOTSUPP;
#endif
}
/******************************************************************************
* mv_eth_tool_set_tx_csum
* Description:
* ethtool enable/disable TX checksum offloading
* INPUT:
* netdev Network device structure pointer
* data Command data
* OUTPUT
* None
* RETURN:
* 0 on success
*
*******************************************************************************/
int mv_eth_tool_set_tx_csum(struct net_device *netdev, uint32_t data)
{
#ifdef CONFIG_MV_ETH_TX_CSUM_OFFLOAD
if (data) {
if (netdev->mtu > MV_ETH_TX_CSUM_MAX_SIZE) {
printk(KERN_ERR "Cannot set TX checksum when MTU > %d\n", MV_ETH_TX_CSUM_MAX_SIZE);
return -EOPNOTSUPP;
}
netdev->features |= NETIF_F_IP_CSUM;
} else {
netdev->features &= ~NETIF_F_IP_CSUM;
}
return 0;
#else
return -EOPNOTSUPP;
#endif /* TX_CSUM_OFFLOAD */
}
/******************************************************************************
* mv_eth_tool_set_tso
* Description:
* ethtool enable/disable TCP segmentation offloading
* INPUT:
* netdev Network device structure pointer
* data Command data
* OUTPUT
* None
* RETURN:
* 0 on success
*
*******************************************************************************/
int mv_eth_tool_set_tso(struct net_device *netdev, uint32_t data)
{
#if defined(CONFIG_MV_ETH_TSO)
if (data)
netdev->features |= NETIF_F_TSO;
else
netdev->features &= ~NETIF_F_TSO;
return 0;
#else
return -EOPNOTSUPP;
#endif
}
/******************************************************************************
* mv_eth_tool_set_ufo
* Description:
* ethtool enable/disable UDP segmentation offloading
* INPUT:
* netdev Network device structure pointer
* data Command data
* OUTPUT
* None
* RETURN:
* 0 on success
*
*******************************************************************************/
int mv_eth_tool_set_ufo(struct net_device *netdev, uint32_t data)
{
/* printk("in %s \n",__FUNCTION__);*/
return -EOPNOTSUPP;
}
/******************************************************************************
* mv_eth_tool_get_strings
* Description:
* ethtool get strings (used for statistics and self-test descriptions)
* INPUT:
* netdev Network device structure pointer
* stringset strings parameters
* OUTPUT
* data output data
* RETURN:
* None
*
*******************************************************************************/
void mv_eth_tool_get_strings(struct net_device *netdev,
uint32_t stringset, uint8_t *data)
{
/* printk("in %s \n",__FUNCTION__);*/
}
/******************************************************************************
* mv_eth_tool_get_stats_count
* Description:
* ethtool get statistics count (number of stat. array entries)
* INPUT:
* netdev Network device structure pointer
* OUTPUT
* None
* RETURN:
* statistics count
*
*******************************************************************************/
int mv_eth_tool_get_stats_count(struct net_device *netdev)
{
/* printk("in %s \n",__FUNCTION__);*/
return 0;
}
/******************************************************************************
* mv_eth_tool_get_ethtool_stats
* Description:
* ethtool get statistics
* INPUT:
* netdev Network device structure pointer
* stats stats parameters
* OUTPUT
* data output data
* RETURN:
* None
*
*******************************************************************************/
void mv_eth_tool_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data)
{
}
const struct ethtool_ops mv_eth_tool_ops = {
.get_settings = mv_eth_tool_get_settings,
.set_settings = mv_eth_tool_set_settings,
.get_drvinfo = mv_eth_tool_get_drvinfo,
.get_regs_len = mv_eth_tool_get_regs_len,
.get_regs = mv_eth_tool_get_regs,
.nway_reset = mv_eth_tool_nway_reset,
.get_link = mv_eth_tool_get_link,
.get_coalesce = mv_eth_tool_get_coalesce,
.set_coalesce = mv_eth_tool_set_coalesce,
.get_ringparam = mv_eth_tool_get_ringparam,
.get_pauseparam = mv_eth_tool_get_pauseparam,
.set_pauseparam = mv_eth_tool_set_pauseparam,
.get_rx_csum = mv_eth_tool_get_rx_csum,
.set_rx_csum = mv_eth_tool_set_rx_csum,
.get_tx_csum = ethtool_op_get_tx_csum,
.set_tx_csum = mv_eth_tool_set_tx_csum,
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
.get_tso = ethtool_op_get_tso,
.set_tso = mv_eth_tool_set_tso,
.get_ufo = ethtool_op_get_ufo,
.set_ufo = mv_eth_tool_set_ufo,
.get_strings = mv_eth_tool_get_strings,
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
.get_stats_count = mv_eth_tool_get_stats_count,
#endif
.get_ethtool_stats = mv_eth_tool_get_ethtool_stats,
};