⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 e1000_ethtool.c

📁 linux系统的网卡驱动包
💻 C
📖 第 1 页 / 共 5 页
字号:
/*******************************************************************************  Intel PRO/1000 Linux driver  Copyright(c) 1999 - 2008 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  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".  Contact Information:  Linux NICS <linux.nics@intel.com>  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//* ethtool support for e1000 */#include <linux/netdevice.h>#ifdef SIOCETHTOOL#include <linux/ethtool.h>#include "e1000.h"#include "e1000_82541.h"#ifdef NETIF_F_HW_VLAN_TX#include <linux/if_vlan.h>#endif#ifdef ETHTOOL_OPS_COMPAT#include "kcompat_ethtool.c"#endif#ifdef ETHTOOL_GSTATSstruct e1000_stats {	char stat_string[ETH_GSTRING_LEN];	int sizeof_stat;	int stat_offset;};#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \		      offsetof(struct e1000_adapter, m)static const struct e1000_stats e1000_gstrings_stats[] = {	{ "rx_packets", E1000_STAT(stats.gprc) },	{ "tx_packets", E1000_STAT(stats.gptc) },	{ "rx_bytes", E1000_STAT(stats.gorc) },	{ "tx_bytes", E1000_STAT(stats.gotc) },	{ "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(net_stats.rx_errors) },	{ "tx_errors", E1000_STAT(net_stats.tx_errors) },	{ "tx_dropped", E1000_STAT(net_stats.tx_dropped) },	{ "multicast", E1000_STAT(stats.mprc) },	{ "collisions", E1000_STAT(stats.colc) },	{ "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) },	{ "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) },	{ "rx_crc_errors", E1000_STAT(stats.crcerrs) },	{ "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) },	{ "rx_no_buffer_count", E1000_STAT(stats.rnbc) },	{ "rx_missed_errors", E1000_STAT(stats.mpc) },	{ "tx_aborted_errors", E1000_STAT(stats.ecol) },	{ "tx_carrier_errors", E1000_STAT(stats.tncrs) },	{ "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) },	{ "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) },	{ "tx_window_errors", E1000_STAT(stats.latecol) },	{ "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) },	{ "tx_timeout_count", E1000_STAT(tx_timeout_count) },	{ "tx_restart_queue", E1000_STAT(restart_queue) },	{ "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.gorc) },	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },	{ "rx_header_split", E1000_STAT(rx_hdr_split) },	{ "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },	{ "tx_smbus", E1000_STAT(stats.mgptc) },	{ "rx_smbus", E1000_STAT(stats.mgprc) },	{ "dropped_smbus", E1000_STAT(stats.mgpdc) },};#ifdef CONFIG_E1000_MQ#define E1000_QUEUE_STATS_LEN \	((((((struct e1000_adapter *)netdev->priv)->num_rx_queues > 1) ? \	  ((struct e1000_adapter *)netdev->priv)->num_rx_queues : 0 ) + \	 (((((struct e1000_adapter *)netdev->priv)->num_tx_queues > 1) ? \	  ((struct e1000_adapter *)netdev->priv)->num_tx_queues : 0 ))) * \	(sizeof(struct e1000_queue_stats) / sizeof(u64)))#else#define E1000_QUEUE_STATS_LEN 0#endif#define E1000_GLOBAL_STATS_LEN	\	sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)#endif /* ETHTOOL_GSTATS */#ifdef ETHTOOL_TESTstatic const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {	"Register test  (offline)", "Eeprom test    (offline)",	"Interrupt test (offline)", "Loopback test  (offline)",	"Link test   (on/offline)"};#define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN#endif /* ETHTOOL_TEST */static int e1000_get_settings(struct net_device *netdev,                              struct ethtool_cmd *ecmd){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	u32 status;	if (hw->phy.media_type == e1000_media_type_copper) {		ecmd->supported = (SUPPORTED_10baseT_Half |		                   SUPPORTED_10baseT_Full |		                   SUPPORTED_100baseT_Half |		                   SUPPORTED_100baseT_Full |		                   SUPPORTED_1000baseT_Full|		                   SUPPORTED_Autoneg |		                   SUPPORTED_TP);		if (hw->phy.type == e1000_phy_ife)			ecmd->supported &= ~SUPPORTED_1000baseT_Full;		ecmd->advertising = ADVERTISED_TP;		if (hw->mac.autoneg == 1) {			ecmd->advertising |= ADVERTISED_Autoneg;			/* the e1000 autoneg seems to match ethtool nicely */			ecmd->advertising |= hw->phy.autoneg_advertised;		}		ecmd->port = PORT_TP;		ecmd->phy_address = hw->phy.addr;		if (hw->mac.type == e1000_82543)			ecmd->transceiver = XCVR_EXTERNAL;		else			ecmd->transceiver = XCVR_INTERNAL;	} else {		ecmd->supported   = (SUPPORTED_1000baseT_Full |				     SUPPORTED_FIBRE |				     SUPPORTED_Autoneg);		ecmd->advertising = (ADVERTISED_1000baseT_Full |				     ADVERTISED_FIBRE |				     ADVERTISED_Autoneg);		ecmd->port = PORT_FIBRE;		if (hw->mac.type >= e1000_82545)			ecmd->transceiver = XCVR_INTERNAL;		else			ecmd->transceiver = XCVR_EXTERNAL;	}	status = E1000_READ_REG(&adapter->hw, E1000_STATUS);	if (status & E1000_STATUS_LU) {		if ((status & E1000_STATUS_SPEED_1000) ||		    hw->phy.media_type != e1000_media_type_copper)			ecmd->speed = SPEED_1000;		else if (status & E1000_STATUS_SPEED_100)			ecmd->speed = SPEED_100;		else			ecmd->speed = SPEED_10;		if ((status & E1000_STATUS_FD) ||		    hw->phy.media_type != e1000_media_type_copper)			ecmd->duplex = DUPLEX_FULL;		else			ecmd->duplex = DUPLEX_HALF;	} else {		ecmd->speed = -1;		ecmd->duplex = -1;	}	ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||			 hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;	return 0;}static int e1000_set_settings(struct net_device *netdev,                              struct ethtool_cmd *ecmd){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	/* When SoL/IDER sessions are active, autoneg/speed/duplex	 * cannot be changed */	if (e1000_check_reset_block(hw)) {		DPRINTK(DRV, ERR, "Cannot change link characteristics "		        "when SoL/IDER is active.\n");		return -EINVAL;	}	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))		msleep(1);	if (ecmd->autoneg == AUTONEG_ENABLE) {		hw->mac.autoneg = 1;		if (hw->phy.media_type == e1000_media_type_fiber)			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |			                             ADVERTISED_FIBRE |			                             ADVERTISED_Autoneg;		else			hw->phy.autoneg_advertised = ecmd->advertising |			                             ADVERTISED_TP |			                             ADVERTISED_Autoneg;		ecmd->advertising = hw->phy.autoneg_advertised;		if (adapter->fc_autoneg)			hw->fc.original_type = e1000_fc_default;	} else {		if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {			clear_bit(__E1000_RESETTING, &adapter->state);			return -EINVAL;		}	}	/* reset the link */	if (netif_running(adapter->netdev)) {		e1000_down(adapter);		e1000_up(adapter);	} else {		e1000_reset(adapter);	}	clear_bit(__E1000_RESETTING, &adapter->state);	return 0;}static void e1000_get_pauseparam(struct net_device *netdev,                                 struct ethtool_pauseparam *pause){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	pause->autoneg =		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);	if (hw->fc.type == e1000_fc_rx_pause)		pause->rx_pause = 1;	else if (hw->fc.type == e1000_fc_tx_pause)		pause->tx_pause = 1;	else if (hw->fc.type == e1000_fc_full) {		pause->rx_pause = 1;		pause->tx_pause = 1;	}}static int e1000_set_pauseparam(struct net_device *netdev,                                struct ethtool_pauseparam *pause){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	int retval = 0;	adapter->fc_autoneg = pause->autoneg;	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))		msleep(1);	if (pause->rx_pause && pause->tx_pause)		hw->fc.type = e1000_fc_full;	else if (pause->rx_pause && !pause->tx_pause)		hw->fc.type = e1000_fc_rx_pause;	else if (!pause->rx_pause && pause->tx_pause)		hw->fc.type = e1000_fc_tx_pause;	else if (!pause->rx_pause && !pause->tx_pause)		hw->fc.type = e1000_fc_none;	hw->fc.original_type = hw->fc.type;	if (adapter->fc_autoneg == AUTONEG_ENABLE) {		hw->fc.type = e1000_fc_default;		if (netif_running(adapter->netdev)) {			e1000_down(adapter);			e1000_up(adapter);		} else {			e1000_reset(adapter);		}	} else {		retval = ((hw->phy.media_type == e1000_media_type_fiber) ?			  e1000_setup_link(hw) : e1000_force_mac_fc(hw));	}	clear_bit(__E1000_RESETTING, &adapter->state);	return retval;}static u32 e1000_get_rx_csum(struct net_device *netdev){	struct e1000_adapter *adapter = netdev_priv(netdev);	return adapter->rx_csum;}static int e1000_set_rx_csum(struct net_device *netdev, u32 data){	struct e1000_adapter *adapter = netdev_priv(netdev);	adapter->rx_csum = data;	if (netif_running(netdev))		e1000_reinit_locked(adapter);	else		e1000_reset(adapter);	return 0;}static u32 e1000_get_tx_csum(struct net_device *netdev){	return (netdev->features & NETIF_F_HW_CSUM) != 0;}static int e1000_set_tx_csum(struct net_device *netdev, u32 data){	struct e1000_adapter *adapter = netdev_priv(netdev);	if (adapter->hw.mac.type < e1000_82543) {		if (!data)			return -EINVAL;		return 0;	}	if (data)		netdev->features |= NETIF_F_HW_CSUM;	else		netdev->features &= ~NETIF_F_HW_CSUM;	return 0;}#ifdef NETIF_F_TSOstatic int e1000_set_tso(struct net_device *netdev, u32 data){	struct e1000_adapter *adapter = netdev_priv(netdev);	int i;	struct net_device *v_netdev;	if (!(adapter->flags & E1000_FLAG_HAS_TSO))		return data ? -EINVAL : 0;	if (data) {		netdev->features |= NETIF_F_TSO;#ifdef NETIF_F_TSO6		if (adapter->flags & E1000_FLAG_HAS_TSO6)			netdev->features |= NETIF_F_TSO6;#endif	} else {		netdev->features &= ~NETIF_F_TSO;#ifdef NETIF_F_TSO6		if (adapter->flags & E1000_FLAG_HAS_TSO6)			netdev->features &= ~NETIF_F_TSO6;#endif#ifdef NETIF_F_HW_VLAN_TX		/* disable TSO on all VLANs if they're present */		if (!adapter->vlgrp)			goto tso_out;		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {			v_netdev = vlan_group_get_device(adapter->vlgrp, i);			if (!v_netdev)				continue;			v_netdev->features &= ~NETIF_F_TSO;#ifdef NETIF_F_TSO6			if (adapter->flags & E1000_FLAG_HAS_TSO6)				v_netdev->features &= ~NETIF_F_TSO6;#endif			vlan_group_set_device(adapter->vlgrp, i, v_netdev);		}#endif	}tso_out:	DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled");	adapter->flags |= E1000_FLAG_TSO_FORCE;	return 0;}#endif /* NETIF_F_TSO */static u32 e1000_get_msglevel(struct net_device *netdev){	struct e1000_adapter *adapter = netdev_priv(netdev);	return adapter->msg_enable;}static void e1000_set_msglevel(struct net_device *netdev, u32 data){	struct e1000_adapter *adapter = netdev_priv(netdev);	adapter->msg_enable = data;}static int e1000_get_regs_len(struct net_device *netdev){#define E1000_REGS_LEN 32	return E1000_REGS_LEN * sizeof(u32);}static void e1000_get_regs(struct net_device *netdev,                           struct ethtool_regs *regs, void *p){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	u32 *regs_buff = p;	u16 phy_data;	memset(p, 0, E1000_REGS_LEN * sizeof(u32));	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;	regs_buff[0]  = E1000_READ_REG(hw, E1000_CTRL);	regs_buff[1]  = E1000_READ_REG(hw, E1000_STATUS);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -