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

📄 e1000_ethtool.c

📁 linux系统的网卡驱动包
💻 C
📖 第 1 页 / 共 5 页
字号:
static int e1000_diag_test_count(struct net_device *netdev){	return E1000_TEST_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, 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;		DPRINTK(HW, 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 */		if (adapter->hw.phy.media_type == e1000_media_type_copper) {			e1000_power_up_phy(&adapter->hw);			e1000_setup_link(&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 = TRUE;		e1000_reset(adapter);		adapter->hw.phy.autoneg_wait_to_complete = FALSE;		clear_bit(__E1000_TESTING, &adapter->state);		if (if_running)			dev_open(netdev);	} else {		DPRINTK(HW, 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 int e1000_wol_exclusion(struct e1000_adapter *adapter,                               struct ethtool_wolinfo *wol){	struct e1000_hw *hw = &adapter->hw;	int retval = 1; /* fail by default */	switch (hw->device_id) {	case E1000_DEV_ID_82542:	case E1000_DEV_ID_82543GC_FIBER:	case E1000_DEV_ID_82543GC_COPPER:	case E1000_DEV_ID_82544EI_FIBER:	case E1000_DEV_ID_82546EB_QUAD_COPPER:	case E1000_DEV_ID_82545EM_FIBER:	case E1000_DEV_ID_82545EM_COPPER:	case E1000_DEV_ID_82546GB_QUAD_COPPER:	case E1000_DEV_ID_82546GB_PCIE:	case E1000_DEV_ID_82571EB_SERDES_QUAD:		/* these don't support WoL at all */		wol->supported = 0;		break;	case E1000_DEV_ID_82546EB_FIBER:	case E1000_DEV_ID_82546GB_FIBER:	case E1000_DEV_ID_82571EB_FIBER:	case E1000_DEV_ID_82571EB_SERDES:	case E1000_DEV_ID_82571EB_COPPER:		/* Wake events not supported on port B */		if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) {			wol->supported = 0;			break;		}		/* return success for non excluded adapter ports */		retval = 0;		break;	case E1000_DEV_ID_82571EB_QUAD_COPPER:	case E1000_DEV_ID_82571EB_QUAD_FIBER:	case E1000_DEV_ID_82571EB_QUAD_COPPER_LP:	case E1000_DEV_ID_82571PT_QUAD_COPPER:	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:		/* quad port adapters only support WoL on port A */		if (!(adapter->flags & E1000_FLAG_QUAD_PORT_A)) {			wol->supported = 0;			break;		}		/* return success for non excluded adapter ports */		retval = 0;		break;	default:		/* dual port cards only support WoL on port A from now on		 * unless it was enabled in the eeprom for port B		 * so exclude FUNC_1 ports from having WoL enabled */		if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1 &&		    !adapter->eeprom_wol) {			wol->supported = 0;			break;		}		retval = 0;	}	return retval;}static void e1000_get_wol(struct net_device *netdev,                          struct ethtool_wolinfo *wol){	struct e1000_adapter *adapter = netdev_priv(netdev);	wol->supported = WAKE_UCAST | WAKE_MCAST |	                 WAKE_BCAST | WAKE_MAGIC;	wol->wolopts = 0;	/* this function will set ->supported = 0 and return 1 if wol is not	 * supported by this hardware */	if (e1000_wol_exclusion(adapter, wol))		return;	/* apply any specific unsupported masks here */	switch (adapter->hw.device_id) {	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:		/* KSP3 does not support UCAST wake-ups */		wol->supported &= ~WAKE_UCAST;		if (adapter->wol & E1000_WUFC_EX)			DPRINTK(DRV, ERR, "Interface does not support "		        "directed (unicast) frame wake-up packets\n");		break;	default:		break;	}	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;	return;}static int e1000_set_wol(struct net_device *netdev,                         struct ethtool_wolinfo *wol){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))		return -EOPNOTSUPP;	if (e1000_wol_exclusion(adapter, wol))		return wol->wolopts ? -EOPNOTSUPP : 0;	switch (hw->device_id) {	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:		if (wol->wolopts & WAKE_UCAST) {			DPRINTK(DRV, ERR, "Interface does not support "		        "directed (unicast) frame wake-up packets\n");			return -EOPNOTSUPP;		}		break;	default:		break;	}	/* 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;	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))		e1000_led_off(&adapter->hw);	else		e1000_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);	if (!data)		data = INT_MAX;	if (adapter->hw.mac.type < e1000_82571) {		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;		}		e1000_setup_led(&adapter->hw);		mod_timer(&adapter->blink_timer, jiffies);		msleep_interruptible(data * 1000);		del_timer_sync(&adapter->blink_timer);	} else if (adapter->hw.phy.type == e1000_phy_ife) {		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);		e1000_write_phy_reg(&(adapter->hw), IFE_PHY_SPECIAL_CONTROL_LED, 0);	} else {		e1000_blink_led(&adapter->hw);		msleep_interruptible(data * 1000);	}	e1000_led_off(&adapter->hw);	clear_bit(E1000_LED_ON, &adapter->led_status);	e1000_cleanup_led(&adapter->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;	return 0;}static int e1000_set_coalesce(struct net_device *netdev,			      struct ethtool_coalesce *ec){	struct e1000_adapter *adapter = netdev_priv(netdev);	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))		return -EINVAL;	if (!(adapter->flags & E1000_FLAG_HAS_INTR_MODERATION))		return -ENOTSUPP;	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)		E1000_WRITE_REG(&adapter->hw, E1000_ITR,			1000000000 / (adapter->itr * 256));	else		E1000_WRITE_REG(&adapter->hw, E1000_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 int e1000_get_stats_count(struct net_device *netdev){	return E1000_STATS_LEN;}static void e1000_get_ethtool_stats(struct net_device *netdev,                                    struct ethtool_stats *stats, u64 *data){	struct e1000_adapter *adapter = netdev_priv(netdev);#ifdef CONFIG_E1000_MQ	u64 *queue_stat;	int stat_count = sizeof(struct e1000_queue_stats) / sizeof(u64);	int j, k;#endif	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;	}#ifdef CONFIG_E1000_MQ	if (adapter->num_tx_queues > 1) {		for (j = 0; j < adapter->num_tx_queues; j++) {			queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats;			for (k = 0; k < stat_count; k++)				data[i + k] = queue_stat[k];			i += k;		}	}	if (adapter->num_rx_queues > 1) {		for (j = 0; j < adapter->num_rx_queues; j++) {			queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats;			for (k = 0; k < stat_count; k++)				data[i + k] = queue_stat[k];			i += k;		}	}#endif/*	BUG_ON(i != E1000_STATS_LEN); */}static void e1000_get_strings(struct net_device *netdev, u32 stringset,                              u8 *data){#ifdef CONFIG_E1000_MQ	struct e1000_adapter *adapter = netdev_priv(netdev);#endif	u8 *p = data;	int i;	switch (stringset) {	case ETH_SS_TEST:		memcpy(data, *e1000_gstrings_test,			E1000_TEST_LEN*ETH_GSTRING_LEN);		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;		}#ifdef CONFIG_E1000_MQ		if (adapter->num_tx_queues > 1) {			for (i = 0; i < adapter->num_tx_queues; i++) {				sprintf(p, "tx_queue_%u_packets", i);				p += ETH_GSTRING_LEN;				sprintf(p, "tx_queue_%u_bytes", i);				p += ETH_GSTRING_LEN;			}		}		if (adapter->num_rx_queues > 1) {			for (i = 0; i < adapter->num_rx_queues; i++) {				sprintf(p, "rx_queue_%u_packets", i);				p += ETH_GSTRING_LEN;				sprintf(p, "rx_queue_%u_bytes", i);				p += ETH_GSTRING_LEN;			}		}#endif/*		BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */		break;	}}static 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_w

⌨️ 快捷键说明

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