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

📄 e1000_ethtool.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	     adapter->hw.mac_type == e1000_82545_rev_3 ||	     adapter->hw.mac_type == e1000_82546_rev_3))) {		adapter->hw.autoneg = TRUE;		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);		if(phy_reg & MII_CR_LOOPBACK) {			phy_reg &= ~MII_CR_LOOPBACK;			e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);			e1000_phy_reset(&adapter->hw);		}	}}static voide1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size){	memset(skb->data, 0xFF, frame_size);	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;	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 inte1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size){	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;	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 inte1000_run_loopback_test(struct e1000_adapter *adapter){	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;	struct pci_dev *pdev = adapter->pdev;	int i, j, k, l, lc, good_cnt, ret_val=0;	unsigned long time;	E1000_WRITE_REG(&adapter->hw, RDT, rxdr->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(rxdr->count <= txdr->count)		lc = ((txdr->count / 64) * 2) + 1;	else		lc = ((rxdr->count / 64) * 2) + 1;	k = l = 0;	for(j = 0; j <= lc; j++) { /* loop count loop */		for(i = 0; i < 64; i++) { /* send the packets */			e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 					1024);			pci_dma_sync_single_for_device(pdev, 					txdr->buffer_info[k].dma,				    	txdr->buffer_info[k].length,				    	PCI_DMA_TODEVICE);			if(unlikely(++k == txdr->count)) k = 0;		}		E1000_WRITE_REG(&adapter->hw, TDT, k);		msec_delay(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, 					rxdr->buffer_info[l].dma,				    	rxdr->buffer_info[l].length,				    	PCI_DMA_FROMDEVICE);				ret_val = e1000_check_lbtest_frame(					rxdr->buffer_info[l].skb,				   	1024);			if(!ret_val)				good_cnt++;			if(unlikely(++l == rxdr->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 && jiffies < (time + 20));		if(good_cnt != 64) {			ret_val = 13; /* ret_val is the same as mis-compare */			break; 		}		if(jiffies >= (time + 2)) {			ret_val = 14; /* error code for time out error */			break;		}	} /* end loop count loop */	return ret_val;}static inte1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data){	if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;	if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;	*data = e1000_run_loopback_test(adapter);	e1000_loopback_cleanup(adapter);	e1000_free_desc_rings(adapter);err_loopback:	return *data;}static inte1000_link_test(struct e1000_adapter *adapter, uint64_t *data){	*data = 0;	if (adapter->hw.media_type == e1000_media_type_internal_serdes) {		int i = 0;		adapter->hw.serdes_link_down = TRUE;		/* On some blade server designs, link establishment		 * could take as long as 2-3 minutes */		do {			e1000_check_for_link(&adapter->hw);			if (adapter->hw.serdes_link_down == FALSE)				return *data;			msec_delay(20);		} while (i++ < 3750);		*data = 1;	} else {		e1000_check_for_link(&adapter->hw);		if(adapter->hw.autoneg)  /* if auto_neg is set wait for it */			msec_delay(4000);		if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {			*data = 1;		}	}	return *data;}static int e1000_diag_test_count(struct net_device *netdev){	return E1000_TEST_LEN;}static voide1000_diag_test(struct net_device *netdev,		   struct ethtool_test *eth_test, uint64_t *data){	struct e1000_adapter *adapter = netdev_priv(netdev);	boolean_t if_running = netif_running(netdev);	if(eth_test->flags == ETH_TEST_FL_OFFLINE) {		/* Offline tests */		/* save speed, duplex, autoneg settings */		uint16_t autoneg_advertised = adapter->hw.autoneg_advertised;		uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;		uint8_t autoneg = adapter->hw.autoneg;		/* 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)			e1000_down(adapter);		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);		if(e1000_loopback_test(adapter, &data[3]))			eth_test->flags |= ETH_TEST_FL_FAILED;		/* restore speed, duplex, autoneg settings */		adapter->hw.autoneg_advertised = autoneg_advertised;		adapter->hw.forced_speed_duplex = forced_speed_duplex;		adapter->hw.autoneg = autoneg;		e1000_reset(adapter);		if(if_running)			e1000_up(adapter);	} else {		/* Online tests */		if(e1000_link_test(adapter, &data[4]))			eth_test->flags |= ETH_TEST_FL_FAILED;		/* Offline tests aren't run; pass by default */		data[0] = 0;		data[1] = 0;		data[2] = 0;		data[3] = 0;	}	msleep_interruptible(4 * 1000);}static voide1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	switch(adapter->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:		wol->supported = 0;		wol->wolopts   = 0;		return;	case E1000_DEV_ID_82546EB_FIBER:	case E1000_DEV_ID_82546GB_FIBER:		/* Wake events only supported on port A for dual fiber */		if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {			wol->supported = 0;			wol->wolopts   = 0;			return;		}		/* Fall Through */	default:		wol->supported = WAKE_UCAST | WAKE_MCAST |				 WAKE_BCAST | WAKE_MAGIC;		wol->wolopts = 0;		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 inte1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	switch(adapter->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:		return wol->wolopts ? -EOPNOTSUPP : 0;	case E1000_DEV_ID_82546EB_FIBER:	case E1000_DEV_ID_82546GB_FIBER:		/* Wake events only supported on port A for dual fiber */		if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)			return wol->wolopts ? -EOPNOTSUPP : 0;		/* Fall Through */	default:		if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))			return -EOPNOTSUPP;		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 voide1000_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 inte1000_phys_id(struct net_device *netdev, uint32_t data){	struct e1000_adapter *adapter = netdev_priv(netdev);	if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))		data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);	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 {		E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |			E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | 			(E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |			(E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |			(E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));		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 inte1000_nway_reset(struct net_device *netdev){	struct e1000_adapter *adapter = netdev_priv(netdev);	if(netif_running(netdev)) {		e1000_down(adapter);		e1000_up(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, uint64_t *data){	struct e1000_adapter *adapter = netdev_priv(netdev);	int i;	e1000_update_stats(adapter);	for(i = 0; i < E1000_STATS_LEN; i++) {		char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;			data[i] = (e1000_gstrings_stats[i].sizeof_stat == 			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;	}}static void e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *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_STATS_LEN; i++) {			memcpy(data + i * ETH_GSTRING_LEN, 			e1000_gstrings_stats[i].stat_string,			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_wol                = e1000_set_wol,	.get_msglevel	        = e1000_get_msglevel,	.set_msglevel	        = e1000_set_msglevel,	.nway_reset             = e1000_nway_reset,	.get_link               = ethtool_op_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_count        = e1000_diag_test_count,	.self_test              = e1000_diag_test,	.get_strings            = e1000_get_strings,	.phys_id                = e1000_phys_id,	.get_stats_count        = e1000_get_stats_count,	.get_ethtool_stats      = e1000_get_ethtool_stats,	.get_perm_addr		= ethtool_op_get_perm_addr,};void e1000_set_ethtool_ops(struct net_device *netdev){	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);}

⌨️ 快捷键说明

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