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

📄 ethtool.c

📁 DELL755 Intel 网卡驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	memset(skb->data, 0xFF, frame_size);	frame_size &= ~1;	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);}static int e1000_check_lbtest_frame(struct sk_buff *skb,				    unsigned int frame_size){	frame_size &= ~1;	if (*(skb->data + 3) == 0xFF)		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&		   (*(skb->data + frame_size / 2 + 12) == 0xAF))			return 0;	return 13;}static int e1000_run_loopback_test(struct e1000_adapter *adapter){	struct e1000_ring *tx_ring = &adapter->test_tx_ring;	struct e1000_ring *rx_ring = &adapter->test_rx_ring;	struct pci_dev *pdev = adapter->pdev;	struct e1000_hw *hw = &adapter->hw;	int i, j, k, l;	int lc;	int good_cnt;	int ret_val = 0;	unsigned long time;	ew32(RDT(0), rx_ring->count - 1);	/*	 * Calculate the loop count based on the largest descriptor ring	 * The idea is to wrap the largest ring a number of times using 64	 * send/receive pairs during each loop	 */	if (rx_ring->count <= tx_ring->count)		lc = ((tx_ring->count / 64) * 2) + 1;	else		lc = ((rx_ring->count / 64) * 2) + 1;	k = 0;	l = 0;	for (j = 0; j <= lc; j++) { /* loop count loop */		for (i = 0; i < 64; i++) { /* send the packets */			e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb,			                          1024);			pci_dma_sync_single_for_device(pdev,					tx_ring->buffer_info[k].dma,					tx_ring->buffer_info[k].length,					PCI_DMA_TODEVICE);			k++;			if (k == tx_ring->count)				k = 0;		}		ew32(TDT(0), k);		msleep(200);		time = jiffies; /* set the start time for the receive */		good_cnt = 0;		do { /* receive the sent packets */			pci_dma_sync_single_for_cpu(pdev,					rx_ring->buffer_info[l].dma, 2048,					PCI_DMA_FROMDEVICE);			ret_val = e1000_check_lbtest_frame(					rx_ring->buffer_info[l].skb, 1024);			if (!ret_val)				good_cnt++;			l++;			if (l == rx_ring->count)				l = 0;			/*			 * time + 20 msecs (200 msecs on 2.4) is more than			 * enough time to complete the receives, if it's			 * exceeded, break and error off			 */		} while ((good_cnt < 64) && !time_after(jiffies, time + 20));		if (good_cnt != 64) {			ret_val = 13; /* ret_val is the same as mis-compare */			break;		}		if (jiffies >= (time + 20)) {			ret_val = 14; /* error code for time out error */			break;		}	} /* end loop count loop */	return ret_val;}static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data){	struct e1000_hw *hw = &adapter->hw;	/*	 * PHY loopback cannot be performed if SoL/IDER	 * sessions are active	 */	if (hw->phy.ops.check_reset_block &&	    hw->phy.ops.check_reset_block(&adapter->hw)) {		e_err("Cannot do PHY loopback test when SoL/IDER is active.\n");		*data = 0;		goto out;	}	*data = e1000_setup_desc_rings(adapter);	if (*data)		goto out;	*data = e1000_setup_loopback_test(adapter);	if (*data)		goto err_loopback;	*data = e1000_run_loopback_test(adapter);	e1000_loopback_cleanup(adapter);err_loopback:	e1000_free_desc_rings(adapter);out:	return *data;}static int e1000_link_test(struct e1000_adapter *adapter, u64 *data){	struct e1000_hw *hw = &adapter->hw;	*data = 0;	if (hw->phy.media_type == e1000_media_type_internal_serdes) {		int i = 0;		hw->mac.serdes_has_link = 0;		/*		 * On some blade server designs, link establishment		 * could take as long as 2-3 minutes		 */		do {			hw->mac.ops.check_for_link(hw);			if (hw->mac.serdes_has_link)				return *data;			msleep(20);		} while (i++ < 3750);		*data = 1;	} else {		hw->mac.ops.check_for_link(hw);		if (hw->mac.autoneg)			msleep(4000);		if (!(er32(STATUS) &		      E1000_STATUS_LU))			*data = 1;	}	return *data;}static int e1000_get_self_test_count(struct net_device *netdev){	return E1000_TEST_LEN;}static int e1000_get_stats_count(struct net_device *netdev){	return E1000_STATS_LEN;}static void e1000_diag_test(struct net_device *netdev,			    struct ethtool_test *eth_test, u64 *data){	struct e1000_adapter *adapter = netdev_priv(netdev);	u16 autoneg_advertised;	u8 forced_speed_duplex;	u8 autoneg;	bool if_running = netif_running(netdev);	set_bit(__E1000_TESTING, &adapter->state);	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {		/* Offline tests */		/* save speed, duplex, autoneg settings */		autoneg_advertised = adapter->hw.phy.autoneg_advertised;		forced_speed_duplex = adapter->hw.mac.forced_speed_duplex;		autoneg = adapter->hw.mac.autoneg;		e_info("offline testing starting\n");		/*		 * Link test performed before hardware reset so autoneg doesn't		 * interfere with test result		 */		if (e1000_link_test(adapter, &data[4]))			eth_test->flags |= ETH_TEST_FL_FAILED;		if (if_running)			/* indicate we're in test mode */			dev_close(netdev);		else			e1000_reset(adapter);		if (e1000_reg_test(adapter, &data[0]))			eth_test->flags |= ETH_TEST_FL_FAILED;		e1000_reset(adapter);		if (e1000_eeprom_test(adapter, &data[1]))			eth_test->flags |= ETH_TEST_FL_FAILED;		e1000_reset(adapter);		if (e1000_intr_test(adapter, &data[2]))			eth_test->flags |= ETH_TEST_FL_FAILED;		e1000_reset(adapter);		/* make sure the phy is powered up */		e1000_power_up_phy(&adapter->hw);		if (e1000_loopback_test(adapter, &data[3]))			eth_test->flags |= ETH_TEST_FL_FAILED;		/* restore speed, duplex, autoneg settings */		adapter->hw.phy.autoneg_advertised = autoneg_advertised;		adapter->hw.mac.forced_speed_duplex = forced_speed_duplex;		adapter->hw.mac.autoneg = autoneg;		/* force this routine to wait until autoneg complete/timeout */		adapter->hw.phy.autoneg_wait_to_complete = 1;		e1000_reset(adapter);		adapter->hw.phy.autoneg_wait_to_complete = 0;		clear_bit(__E1000_TESTING, &adapter->state);		if (if_running)			dev_open(netdev);	} else {		e_info("online testing starting\n");		/* Online tests */		if (e1000_link_test(adapter, &data[4]))			eth_test->flags |= ETH_TEST_FL_FAILED;		/* Online tests aren't run; pass by default */		data[0] = 0;		data[1] = 0;		data[2] = 0;		data[3] = 0;		clear_bit(__E1000_TESTING, &adapter->state);	}	msleep_interruptible(4 * 1000);}static void e1000_get_wol(struct net_device *netdev,			  struct ethtool_wolinfo *wol){	struct e1000_adapter *adapter = netdev_priv(netdev);	wol->supported = 0;	wol->wolopts = 0;	if (!(adapter->flags & FLAG_HAS_WOL))		return;	wol->supported = WAKE_UCAST | WAKE_MCAST |	                 WAKE_BCAST | WAKE_MAGIC |	                 WAKE_PHY | WAKE_ARP;	/* apply any specific unsupported masks here */	if (adapter->flags & FLAG_NO_WAKE_UCAST) {		wol->supported &= ~WAKE_UCAST;		if (adapter->wol & E1000_WUFC_EX)			e_err("Interface does not support directed (unicast)"			      " frame wake-up packets\n");	}	if (adapter->wol & E1000_WUFC_EX)		wol->wolopts |= WAKE_UCAST;	if (adapter->wol & E1000_WUFC_MC)		wol->wolopts |= WAKE_MCAST;	if (adapter->wol & E1000_WUFC_BC)		wol->wolopts |= WAKE_BCAST;	if (adapter->wol & E1000_WUFC_MAG)		wol->wolopts |= WAKE_MAGIC;	if (adapter->wol & E1000_WUFC_LNKC)		wol->wolopts |= WAKE_PHY;	if (adapter->wol & E1000_WUFC_ARP)		wol->wolopts |= WAKE_ARP;}static int e1000_set_wol(struct net_device *netdev,			 struct ethtool_wolinfo *wol){	struct e1000_adapter *adapter = netdev_priv(netdev);	if (wol->wolopts & WAKE_MAGICSECURE)		return -EOPNOTSUPP;	if (!(adapter->flags & FLAG_HAS_WOL))		return wol->wolopts ? -EOPNOTSUPP : 0;	/* these settings will always override what we currently have */	adapter->wol = 0;	if (wol->wolopts & WAKE_UCAST)		adapter->wol |= E1000_WUFC_EX;	if (wol->wolopts & WAKE_MCAST)		adapter->wol |= E1000_WUFC_MC;	if (wol->wolopts & WAKE_BCAST)		adapter->wol |= E1000_WUFC_BC;	if (wol->wolopts & WAKE_MAGIC)		adapter->wol |= E1000_WUFC_MAG;	if (wol->wolopts & WAKE_PHY)		adapter->wol |= E1000_WUFC_LNKC;	if (wol->wolopts & WAKE_ARP)		adapter->wol |= E1000_WUFC_ARP;	return 0;}/* toggle LED 4 times per second = 2 "blinks" per second */#define E1000_ID_INTERVAL	(HZ/4)/* bit defines for adapter->led_status */#define E1000_LED_ON		0static void e1000_led_blink_callback(unsigned long data){	struct e1000_adapter *adapter = (struct e1000_adapter *) data;	if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))		adapter->hw.mac.ops.led_off(&adapter->hw);	else		adapter->hw.mac.ops.led_on(&adapter->hw);	mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);}static int e1000_phys_id(struct net_device *netdev, u32 data){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	if (!data)		data = INT_MAX;	if ((hw->phy.type == e1000_phy_ife) ||	    (hw->mac.type == e1000_82574)) {		if (!adapter->blink_timer.function) {			init_timer(&adapter->blink_timer);			adapter->blink_timer.function =				e1000_led_blink_callback;			adapter->blink_timer.data = (unsigned long) adapter;		}		mod_timer(&adapter->blink_timer, jiffies);		msleep_interruptible(data * 1000);		del_timer_sync(&adapter->blink_timer);	if (hw->phy.type == e1000_phy_ife)			hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,			                      0);	} else {		hw->mac.ops.blink_led(hw);		msleep_interruptible(data * 1000);	}	hw->mac.ops.led_off(hw);	clear_bit(E1000_LED_ON, &adapter->led_status);	hw->mac.ops.cleanup_led(hw);	return 0;}static int e1000_get_coalesce(struct net_device *netdev,			      struct ethtool_coalesce *ec){	struct e1000_adapter *adapter = netdev_priv(netdev);	if (adapter->itr_setting <= 3)		ec->rx_coalesce_usecs = adapter->itr_setting;	else		ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;	ec->stats_block_coalesce_usecs = adapter->stats_freq_us;	return 0;}static int e1000_set_coalesce(struct net_device *netdev,			      struct ethtool_coalesce *ec){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||	    ((ec->rx_coalesce_usecs > 3) &&	     (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||	    (ec->rx_coalesce_usecs == 2) ||	    (ec->stats_block_coalesce_usecs > (10 * 1000000)))		return -EINVAL;	adapter->stats_freq_us = ec->stats_block_coalesce_usecs;	if (ec->rx_coalesce_usecs <= 3) {		adapter->itr = 20000;		adapter->itr_setting = ec->rx_coalesce_usecs;	} else {		adapter->itr = (1000000 / ec->rx_coalesce_usecs);		adapter->itr_setting = adapter->itr & ~3;	}	if (adapter->itr_setting != 0)		ew32(ITR, 1000000000 / (adapter->itr * 256));	else		ew32(ITR, 0);	return 0;}static int e1000_nway_reset(struct net_device *netdev){	struct e1000_adapter *adapter = netdev_priv(netdev);	if (netif_running(netdev))		e1000_reinit_locked(adapter);	return 0;}static void e1000_get_ethtool_stats(struct net_device *netdev,				    struct ethtool_stats *stats,				    u64 *data){	struct e1000_adapter *adapter = netdev_priv(netdev);	int i;	e1000_update_stats(adapter);	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {		char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;		data[i] = (e1000_gstrings_stats[i].sizeof_stat ==			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;	}}static void e1000_get_strings(struct net_device *netdev, u32 stringset,			      u8 *data){	u8 *p = data;	int i;	switch (stringset) {	case ETH_SS_TEST:		memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test));		break;	case ETH_SS_STATS:		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {			memcpy(p, e1000_gstrings_stats[i].stat_string,			       ETH_GSTRING_LEN);			p += ETH_GSTRING_LEN;		}		break;	}}static const struct ethtool_ops e1000_ethtool_ops = {	.get_settings		= e1000_get_settings,	.set_settings		= e1000_set_settings,	.get_drvinfo		= e1000_get_drvinfo,	.get_regs_len		= e1000_get_regs_len,	.get_regs		= e1000_get_regs,	.get_wol		= e1000_get_wol,	.set_wol		= e1000_set_wol,	.get_msglevel		= e1000_get_msglevel,	.set_msglevel		= e1000_set_msglevel,	.nway_reset		= e1000_nway_reset,	.get_link		= e1000_get_link,	.get_eeprom_len		= e1000_get_eeprom_len,	.get_eeprom		= e1000_get_eeprom,	.set_eeprom		= e1000_set_eeprom,	.get_ringparam		= e1000_get_ringparam,	.set_ringparam		= e1000_set_ringparam,	.get_pauseparam		= e1000_get_pauseparam,	.set_pauseparam		= e1000_set_pauseparam,	.get_rx_csum		= e1000_get_rx_csum,	.set_rx_csum		= e1000_set_rx_csum,	.get_tx_csum		= e1000_get_tx_csum,	.set_tx_csum		= e1000_set_tx_csum,	.get_sg			= ethtool_op_get_sg,	.set_sg			= ethtool_op_set_sg,#ifdef NETIF_F_TSO	.get_tso		= ethtool_op_get_tso,	.set_tso		= e1000_set_tso,#endif	.self_test		= e1000_diag_test,	.get_strings		= e1000_get_strings,	.phys_id		= e1000_phys_id,	.get_ethtool_stats	= e1000_get_ethtool_stats,	.self_test_count	= e1000_get_self_test_count,	.get_stats_count	= e1000_get_stats_count,	.get_coalesce		= e1000_get_coalesce,	.set_coalesce		= e1000_set_coalesce,};void e1000_set_ethtool_ops(struct net_device *netdev){	/* have to "undeclare" const on this struct to remove warnings */	SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&e1000_ethtool_ops);}#endif /* SIOCETHTOOL */

⌨️ 快捷键说明

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