📄 skethtool.c
字号:
/****************************************************************************** * * Name: skethtool.c * Project: GEnesis, PCI Gigabit Ethernet Adapter * Version: $Revision: 1.9.2.10 $ * Date: $Date: 2008/04/09 12:16:01 $ * Purpose: All functions regarding ethtool handling * ******************************************************************************//****************************************************************************** * * (C)Copyright 1998-2002 SysKonnect GmbH. * (C)Copyright 2002-2007 Marvell. * * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet * Server Adapters. * * Address all question to: gr-msgg-linux@marvell.com * * LICENSE: * (C)Copyright Marvell. * * 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; either version 2 of the License, or * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. * /LICENSE * *****************************************************************************/#include "h/skdrv1st.h"#include "h/skdrv2nd.h"#include "h/skversion.h"#include <linux/ethtool.h>#include <linux/module.h>#include <linux/timer.h>/****************************************************************************** * * Local Functions * *****************************************************************************/static void toggleLeds(unsigned long ptr);/****************************************************************************** * * External Functions and Data * *****************************************************************************/extern void SkDimDisableModeration(SK_AC *pAC, int CurrentModeration);extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);/****************************************************************************** * * Defines * *****************************************************************************/#ifndef ETHT_STATSTRING_LEN#define ETHT_STATSTRING_LEN 32#endif#define ENABLE_FUTURE_ETH#define SK98LIN_STAT(m) sizeof(((SK_AC *)0)->m),offsetof(SK_AC, m)#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \ SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \ SUPPORTED_TP)#define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \ ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \ ADVERTISED_TP)#define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \ SUPPORTED_FIBRE | \ SUPPORTED_Autoneg)#define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \ ADVERTISED_FIBRE | \ ADVERTISED_Autoneg)struct sk98lin_stats { char stat_string[ETHT_STATSTRING_LEN]; int sizeof_stat; int stat_offset;};static struct sk98lin_stats sk98lin_etht_stats_port0[] = { { "rx_packets" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxOkCts) }, { "tx_packets" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxOkCts) }, { "rx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxOctetsOkCts) }, { "tx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxOctetsOkCts) }, { "rx_errors" , SK98LIN_STAT(PnmiStruct.InErrorsCts) }, { "tx_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxSingleCollisionCts) }, { "rx_dropped" , SK98LIN_STAT(PnmiStruct.RxNoBufCts) }, { "tx_dropped" , SK98LIN_STAT(PnmiStruct.TxNoBufCts) }, { "multicasts" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxMulticastOkCts) }, { "collisions" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxSingleCollisionCts) }, { "rx_length_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxRuntCts) }, { "rx_buffer_overflow_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFifoOverflowCts) }, { "rx_crc_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFcsCts) }, { "rx_frame_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFramingCts) }, { "rx_too_short_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxShortsCts) }, { "rx_too_long_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxTooLongCts) }, { "rx_carrier_extension_errors", SK98LIN_STAT(PnmiStruct.Stat[0].StatRxCextCts) }, { "rx_symbol_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxSymbolCts) }, { "rx_llc_mac_size_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxIRLengthCts) }, { "rx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxCarrierCts) }, { "rx_jabber_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxJabberCts) }, { "rx_missed_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxMissedCts) }, { "tx_abort_collision_errors" , SK98LIN_STAT(stats.tx_aborted_errors) }, { "tx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxCarrierCts) }, { "tx_buffer_underrun_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxFifoUnderrunCts) }, { "tx_heartbeat_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxCarrierCts) } , { "tx_window_errors" , SK98LIN_STAT(stats.tx_window_errors) }};static struct sk98lin_stats sk98lin_etht_stats_port1[] = { { "rx_packets" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxOkCts) }, { "tx_packets" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxOkCts) }, { "rx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxOctetsOkCts) }, { "tx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxOctetsOkCts) }, { "rx_errors" , SK98LIN_STAT(PnmiStruct.InErrorsCts) }, { "tx_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxSingleCollisionCts) }, { "rx_dropped" , SK98LIN_STAT(PnmiStruct.RxNoBufCts) }, { "tx_dropped" , SK98LIN_STAT(PnmiStruct.TxNoBufCts) }, { "multicasts" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxMulticastOkCts) }, { "collisions" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxSingleCollisionCts) }, { "rx_length_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxRuntCts) }, { "rx_buffer_overflow_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFifoOverflowCts) }, { "rx_crc_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFcsCts) }, { "rx_frame_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFramingCts) }, { "rx_too_short_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxShortsCts) }, { "rx_too_long_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxTooLongCts) }, { "rx_carrier_extension_errors", SK98LIN_STAT(PnmiStruct.Stat[1].StatRxCextCts) }, { "rx_symbol_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxSymbolCts) }, { "rx_llc_mac_size_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxIRLengthCts) }, { "rx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxCarrierCts) }, { "rx_jabber_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxJabberCts) }, { "rx_missed_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxMissedCts) }, { "tx_abort_collision_errors" , SK98LIN_STAT(stats.tx_aborted_errors) }, { "tx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxCarrierCts) }, { "tx_buffer_underrun_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxFifoUnderrunCts) }, { "tx_heartbeat_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxCarrierCts) } , { "tx_window_errors" , SK98LIN_STAT(stats.tx_window_errors) }};static int DuplexAutoNegConfMap[9][3]= { { -1 , -1 , -1 }, { 0 , -1 , -1 }, { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE }, { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE }, { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE }, { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE }, { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE }, { SK_LMODE_AUTOSENSE , -1 , -1 }, { SK_LMODE_INDETERMINATED, -1 , -1 }};static int SpeedConfMap[6][2] = { { 0 , -1 }, { SK_LSPEED_AUTO , -1 }, { SK_LSPEED_10MBPS , SPEED_10 }, { SK_LSPEED_100MBPS , SPEED_100 }, { SK_LSPEED_1000MBPS , SPEED_1000 }, { SK_LSPEED_INDETERMINATED, -1 }};static int AdvSpeedMap[6][2] = { { 0 , -1 }, { SK_LSPEED_AUTO , -1 }, { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full }, { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full }, { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full}, { SK_LSPEED_INDETERMINATED, -1 }};#define SK98LIN_STATS_LEN sizeof(sk98lin_etht_stats_port0) / sizeof(struct sk98lin_stats)static int nbrBlinkQuarterSeconds;static int currentPortIndex;static SK_BOOL isLocateNICrunning = SK_FALSE;static SK_BOOL isDualNetCard = SK_FALSE;static SK_BOOL doSwitchLEDsOn = SK_FALSE;static SK_BOOL boardWasDown[2] = { SK_FALSE, SK_FALSE };static struct timer_list locateNICtimer;/****************************************************************************** * * Ethtool Functions * *****************************************************************************//***************************************************************************** * * SkGeGetSettings - retrieves the current settings of the selected adapter * * Description: * The current configuration of the selected adapter is returned. * This configuration involves a)speed, b)duplex and c)autoneg plus * a number of other variables. * * Returns: N/A * */int SkGeGetSettings(struct net_device *dev, struct ethtool_cmd *ecmd){ DEV_NET *pNet = (DEV_NET*) dev->priv; SK_AC *pAC = pNet->pAC; int port = pNet->PortNr; SK_GEPORT *pPort = &pAC->GIni.GP[port]; ecmd->phy_address = port; ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1]; ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1]; ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2]; ecmd->transceiver = XCVR_INTERNAL; if (pAC->GIni.GICopperType) { ecmd->port = PORT_TP; ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg); if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { ecmd->supported &= ~(SUPPORTED_1000baseT_Half); } if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) || (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P)) { ecmd->supported &= ~(SUPPORTED_1000baseT_Half); ecmd->supported &= ~(SUPPORTED_1000baseT_Full); } if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) { ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1]; if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { ecmd->advertising &= ~(SUPPORTED_1000baseT_Half); } } else { ecmd->advertising = ecmd->supported; } if (ecmd->autoneg == AUTONEG_ENABLE) { ecmd->advertising |= ADVERTISED_Autoneg; } else { ecmd->advertising = ADVERTISED_TP; } } else { ecmd->port = PORT_FIBRE; ecmd->supported = (SUPP_FIBRE_ALL); ecmd->advertising = (ADV_FIBRE_ALL); } return(0);}/***************************************************************************** * * SkGeGetDrvInfo - returns generic driver and adapter information * * Description: * Generic driver information is returned via this function, such as * the name of the driver, its version and and firmware version. * In addition to this, the location of the selected adapter is * returned as a bus info string (e.g. '01:05.0'). * * Returns: N/A * */void SkGeGetDrvInfo(struct net_device *dev, struct ethtool_drvinfo *ecmd){ DEV_NET *pNet = (DEV_NET*) dev->priv; SK_AC *pAC = pNet->pAC; char versionString[32]; snprintf(versionString, 32, "%s (%s)", VER_STRING, PATCHLEVEL); strncpy(ecmd->driver, DRIVER_FILE_NAME , 32); strncpy(ecmd->version, versionString , 32); strncpy(ecmd->fw_version, "N/A", 32); strncpy(ecmd->bus_info, pci_name(pAC->PciDev), 32);#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) ecmd->n_stats = SK98LIN_STATS_LEN;#endif}/***************************************************************************** * * SkGeGetWolSettings - retrieves the WOL settings of the * selected adapter * * Description: * All current WOL settings of a selected adapter are placed in the * passed ethtool_wolinfo structure and are returned to the caller. * * Returns: N/A * */void SkGeGetWolSettings(struct net_device *dev, struct ethtool_wolinfo *ecmd){ DEV_NET *pNet = (DEV_NET*) dev->priv; SK_AC *pAC = pNet->pAC; ecmd->supported = pAC->WolInfo.SupportedWolOptions; ecmd->wolopts = pAC->WolInfo.ConfiguredWolOptions;}/***************************************************************************** * * SkGeGetPauseParam - retrieves the pause parameters * * Description: * All current pause parameters of a selected adapter are placed * in the passed ethtool_pauseparam structure and are returned. * * Returns: N/A * */void SkGeGetPauseParam(struct net_device *dev, struct ethtool_pauseparam *ecmd){ DEV_NET *pNet = (DEV_NET*) dev->priv; SK_AC *pAC = pNet->pAC; int port = pNet->PortNr; SK_GEPORT *pPort = &pAC->GIni.GP[port]; /* Get the pause parameters */ ecmd->rx_pause = 0; ecmd->tx_pause = 0; if (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND) { ecmd->tx_pause = 1; } if ((pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) || (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM)) { ecmd->tx_pause = 1; ecmd->rx_pause = 1; } if ((ecmd->rx_pause == 0) && (ecmd->tx_pause == 0)) { ecmd->autoneg = SK_FALSE; } else { ecmd->autoneg = SK_TRUE; }}/***************************************************************************** * * SkGeGetCoalesce - retrieves the IRQ moderation settings * * Description: * All current IRQ moderation settings of a selected adapter are placed * in the passed ethtool_coalesce structure and are returned. * * Returns: N/A * */int SkGeGetCoalesce(struct net_device *dev, struct ethtool_coalesce *ecmd){ DEV_NET *pNet = (DEV_NET*) dev->priv; SK_AC *pAC = pNet->pAC; DIM_INFO *Info = &pAC->DynIrqModInfo; SK_BOOL UseTxIrqModeration = SK_FALSE; SK_BOOL UseRxIrqModeration = SK_FALSE; if (Info->IntModTypeSelect != C_INT_MOD_NONE) { if (CHIP_ID_YUKON_2(pAC)) { UseRxIrqModeration = SK_TRUE; UseTxIrqModeration = SK_TRUE; } else { if ((Info->MaskIrqModeration == IRQ_MASK_RX_ONLY) || (Info->MaskIrqModeration == IRQ_MASK_SP_RX) || (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) { UseRxIrqModeration = SK_TRUE; } if ((Info->MaskIrqModeration == IRQ_MASK_TX_ONLY) || (Info->MaskIrqModeration == IRQ_MASK_SP_TX) || (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) { UseTxIrqModeration = SK_TRUE; } } if (UseRxIrqModeration) { ecmd->rx_coalesce_usecs = 1000000 / Info->MaxModIntsPerSec; } if (UseTxIrqModeration) { ecmd->tx_coalesce_usecs = 1000000 / Info->MaxModIntsPerSec; } if (Info->IntModTypeSelect == C_INT_MOD_DYNAMIC) { ecmd->rate_sample_interval = Info->DynIrqModSampleInterval; if (UseRxIrqModeration) { ecmd->use_adaptive_rx_coalesce = 1; ecmd->rx_coalesce_usecs_low = 1000000 / Info->MaxModIntsPerSecLowerLimit; ecmd->rx_coalesce_usecs_high = 1000000 / Info->MaxModIntsPerSecUpperLimit; } if (UseTxIrqModeration) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -