📄 at_ethtool.c
字号:
#include "at.h"
#include "at_hw.h"
#ifdef SIOCETHTOOL
#include <asm/uaccess.h>
extern char at_driver_name[];
extern char at_driver_version[];
#ifdef SIOCGMIIPHY
extern int at_set_spd_dplx(struct at_adapter* adapter,uint16_t spddplx);
#endif
extern int32_t at_up(struct at_adapter* adapter);
extern void at_down(struct at_adapter* adapter);
extern void at_reset(struct at_adapter* adapter);
extern int32_t at_setup_ring_resources(struct at_adapter* adapter);
extern void at_free_ring_resources(struct at_adapter* adapter);
#ifdef ETHTOOL_GSTATS
struct at_stats {
char stat_string[ETH_GSTRING_LEN];
int sizeof_stat;
int stat_offset;
};
#define AT_STAT(m) sizeof(((struct at_adapter *)0)->m), \
offsetof(struct at_adapter, m)
static struct at_stats at_gstrings_stats[] = {
{ "rx_packets", AT_STAT(soft_stats.rx_packets) },
{ "tx_packets", AT_STAT(soft_stats.tx_packets) },
{ "rx_bytes", AT_STAT(soft_stats.rx_bytes) },
{ "tx_bytes", AT_STAT(soft_stats.tx_bytes) },
{ "rx_errors", AT_STAT(soft_stats.rx_errors) },
{ "tx_errors", AT_STAT(soft_stats.tx_errors) },
{ "rx_dropped", AT_STAT(net_stats.rx_dropped) },
{ "tx_dropped", AT_STAT(net_stats.tx_dropped) },
{ "multicast", AT_STAT(soft_stats.multicast) },
{ "collisions", AT_STAT(soft_stats.collisions) },
{ "rx_length_errors", AT_STAT(soft_stats.rx_length_errors) },
{ "rx_over_errors", AT_STAT(soft_stats.rx_missed_errors) },
{ "rx_crc_errors", AT_STAT(soft_stats.rx_crc_errors) },
{ "rx_frame_errors", AT_STAT(soft_stats.rx_frame_errors) },
{ "rx_fifo_errors", AT_STAT(soft_stats.rx_fifo_errors) },
{ "rx_missed_errors", AT_STAT(soft_stats.rx_missed_errors) },
{ "tx_aborted_errors", AT_STAT(soft_stats.tx_aborted_errors) },
{ "tx_carrier_errors", AT_STAT(soft_stats.tx_carrier_errors) },
{ "tx_fifo_errors", AT_STAT(soft_stats.tx_fifo_errors) },
{ "tx_window_errors", AT_STAT(soft_stats.tx_window_errors) },
{ "tx_abort_exce_coll", AT_STAT(soft_stats.excecol) },
{ "tx_abort_late_coll", AT_STAT(soft_stats.latecol) },
{ "tx_deferred_ok", AT_STAT(soft_stats.deffer) },
{ "tx_single_coll_ok", AT_STAT(soft_stats.scc) },
{ "tx_multi_coll_ok", AT_STAT(soft_stats.mcc) },
{ "tx_underun", AT_STAT(soft_stats.tx_underun) },
{ "tx_trunc", AT_STAT(soft_stats.tx_trunc) },
{ "tx_pause", AT_STAT(soft_stats.tx_pause) },
{ "rx_pause", AT_STAT(soft_stats.rx_pause) },
{ "rx_rrd_ov", AT_STAT(soft_stats.rx_rrd_ov) },
{ "rx_trunc", AT_STAT(soft_stats.rx_trunc) }
};
#define AT_STATS_LEN \
sizeof(at_gstrings_stats) / sizeof(struct at_stats)
#endif /* ETHTOOL_GSTATS */
#ifdef ETHTOOL_GWOL
static void
at_ethtool_gwol(struct at_adapter *adapter, struct ethtool_wolinfo *wol)
{
wol->supported =
WAKE_UCAST | WAKE_MCAST |
WAKE_BCAST | WAKE_MAGIC;
wol->wolopts = 0;
if(adapter->wol & AT_WUFC_EX)
wol->wolopts |= WAKE_UCAST;
if(adapter->wol & AT_WUFC_MC)
wol->wolopts |= WAKE_MCAST;
if(adapter->wol & AT_WUFC_BC)
wol->wolopts |= WAKE_BCAST;
if(adapter->wol & AT_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
return;
}
#endif /* ETHTOOL_GWOL */
#ifdef ETHTOOL_SWOL
static int
at_ethtool_swol(struct at_adapter *adapter, struct ethtool_wolinfo *wol)
{
if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
adapter->wol = 0;
if(wol->wolopts & WAKE_UCAST)
adapter->wol |= AT_WUFC_EX;
if(wol->wolopts & WAKE_MCAST)
adapter->wol |= AT_WUFC_MC;
if(wol->wolopts & WAKE_BCAST)
adapter->wol |= AT_WUFC_BC;
if(wol->wolopts & WAKE_MAGIC)
adapter->wol |= AT_WUFC_MAG;
return 0;
}
#endif /* ETHTOOL_SWOL */
static int
at_ethtool_sset(struct at_adapter *adapter, struct ethtool_cmd *ecmd)
{
struct at_hw *hw = &adapter->hw;
uint16_t phy_data;
int ret_val = 0;
uint16_t old_media_type = hw->MediaType;
if(netif_running(adapter->netdev)) {
at_down(adapter);
}
//michael add 2005-11-17
DEBUGOUT("enter at_ethtool_sset---michael debug\n");
if(ecmd->autoneg == AUTONEG_ENABLE) {
hw->MediaType = MEDIA_TYPE_AUTO_SENSOR;
} else {
if (ecmd->speed == SPEED_1000) {
if (ecmd->duplex != DUPLEX_FULL) {
printk(KERN_WARNING"can't force to 1000MHalf !\n");
ret_val = -EINVAL;
goto exit_sset;
}
hw->MediaType = MEDIA_TYPE_1000M_FULL;
} else if (ecmd->speed == SPEED_100) {
if (ecmd->duplex == DUPLEX_FULL) {
hw->MediaType = MEDIA_TYPE_100M_FULL;
} else {
hw->MediaType = MEDIA_TYPE_100M_HALF;
}
} else {
if (ecmd->duplex == DUPLEX_FULL) {
hw->MediaType = MEDIA_TYPE_10M_FULL;
} else {
hw->MediaType = MEDIA_TYPE_10M_HALF;
}
}
}
switch (hw->MediaType)
{
case MEDIA_TYPE_AUTO_SENSOR:
ecmd->advertising =
ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full |
ADVERTISED_1000baseT_Full|
ADVERTISED_Autoneg |
ADVERTISED_TP;
break;
case MEDIA_TYPE_1000M_FULL:
ecmd->advertising =
ADVERTISED_1000baseT_Full|
ADVERTISED_Autoneg |
ADVERTISED_TP;
break;
default:
ecmd->advertising = 0;
break;
}
if(at_phy_setup_autoneg_adv(hw)) {
ret_val = -EINVAL;
goto exit_sset;
}
if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR ||
hw->MediaType == MEDIA_TYPE_1000M_FULL) {
phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
} else {
switch (hw->MediaType)
{
case MEDIA_TYPE_100M_FULL:
phy_data = MII_CR_FULL_DUPLEX|MII_CR_SPEED_100|MII_CR_RESET;
break;
case MEDIA_TYPE_100M_HALF:
phy_data = MII_CR_SPEED_100|MII_CR_RESET;
break;
case MEDIA_TYPE_10M_FULL:
phy_data = MII_CR_FULL_DUPLEX|MII_CR_SPEED_10|MII_CR_RESET;
break;
default: // MEDIA_TYPE_10M_HALF:
phy_data = MII_CR_SPEED_10|MII_CR_RESET;
break;
}
}
at_write_phy_reg(hw, MII_BMCR, phy_data);
exit_sset:
if (ret_val) {
hw->MediaType = old_media_type;
}
if(netif_running(adapter->netdev)) {
at_up(adapter);
} else if (!ret_val) {
at_reset(adapter);
}
return ret_val;
}
static void
at_ethtool_gset(struct at_adapter *adapter, struct ethtool_cmd *ecmd)
{
struct at_hw *hw = &adapter->hw;
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;
if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR ||
hw->MediaType == MEDIA_TYPE_1000M_FULL) {
ecmd->advertising |= ADVERTISED_Autoneg;
if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR) {
ecmd->advertising |= ADVERTISED_Autoneg;
ecmd->advertising |=
(ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
ADVERTISED_100baseT_Full |
ADVERTISED_1000baseT_Full );
} else {
ecmd->advertising |=
(ADVERTISED_1000baseT_Full);
}
}
ecmd->port = PORT_TP;
ecmd->phy_address = 0;
ecmd->transceiver = XCVR_INTERNAL;
if(netif_carrier_ok(adapter->netdev))
{
uint16_t link_speed, link_duplex;
at_get_speed_and_duplex(hw, &link_speed, &link_duplex);
ecmd->speed = link_speed;
if(link_duplex == FULL_DUPLEX)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
} else {
ecmd->speed = -1;
ecmd->duplex = -1;
}
if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR ||
hw->MediaType == MEDIA_TYPE_1000M_FULL) {
ecmd->autoneg = AUTONEG_ENABLE;
} else {
ecmd->autoneg = AUTONEG_DISABLE;
}
}
#ifdef ETHTOOL_GDRVINFO
static void
at_ethtool_gdrvinfo(struct at_adapter *adapter,
struct ethtool_drvinfo *drvinfo)
{
strncpy(drvinfo->driver, at_driver_name, 32);
strncpy(drvinfo->version, at_driver_version, 32);
strncpy(drvinfo->fw_version, "N/A", 32);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
#ifdef ETHTOOL_GEEPROM
drvinfo->eedump_len = 48;
#endif//ETHTOOL_GEEPROM
}
#endif /* ETHTOOL_GDRVINFO */
#ifdef ETHTOOL_GRINGPARAM
static int
at_ethtool_gring(struct at_adapter *adapter,
struct ethtool_ringparam *ring)
{
struct at_tpd_ring *txdr = &adapter->tpd_ring;
struct at_rfd_ring *rxdr = &adapter->rfd_ring;
ring->rx_max_pending = 2048;
ring->tx_max_pending = 1024;
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;
return 0;
}
#endif /* ETHTOOL_GRINGPARAM */
#ifdef ETHTOOL_SRINGPARAM
static int
at_ethtool_sring(struct at_adapter *adapter,
struct ethtool_ringparam *ring)
{
int err;
struct at_tpd_ring *tpdr = &adapter->tpd_ring;
struct at_rrd_ring *rrdr = &adapter->rrd_ring;
struct at_rfd_ring *rfdr = &adapter->rfd_ring;
struct at_tpd_ring tpd_old, tpd_new;
struct at_rfd_ring rfd_old, rfd_new;
struct at_rrd_ring rrd_old , rrd_new;
tpd_old = adapter->tpd_ring;
rfd_old = adapter->rfd_ring;
rrd_old = adapter->rrd_ring;
if(netif_running(adapter->netdev))
at_down(adapter);
rfdr->count = (uint16_t)max(ring->rx_pending, (uint32_t)32);
rfdr->count = rfdr->count>2048 ? 2048 : rfdr->count;
rfdr->count = (rfdr->count+3)&~3;
rrdr->count = rfdr->count;
tpdr->count = (uint16_t)max(ring->tx_pending, (uint32_t)16);
tpdr->count = tpdr->count>1024 ? 1024 : tpdr->count;
tpdr->count = (tpdr->count+3)&~3;
if(netif_running(adapter->netdev)) {
/* try to get new resources before deleting old */
if ((err = at_setup_ring_resources(adapter)))
goto err_setup_ring;
/* save the new, restore the old in order to free it,
* then restore the new back again */
rfd_new = adapter->rfd_ring;
rrd_new = adapter->rrd_ring;
tpd_new = adapter->tpd_ring;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -