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

📄 e1000_ethtool.c

📁 82546千兆网卡驱动程序,支持该系列所有芯片
💻 C
📖 第 1 页 / 共 4 页
字号:
	uint16_t *eeprom_buff;	int first_word, last_word;	int ret_val = 0;	uint16_t i;	if (eeprom->len == 0)		return -EINVAL;	eeprom->magic = hw->vendor_id | (hw->device_id << 16);	first_word = eeprom->offset >> 1;	last_word = (eeprom->offset + eeprom->len - 1) >> 1;	eeprom_buff = kmalloc(sizeof(uint16_t) *			(last_word - first_word + 1), GFP_KERNEL);	if (!eeprom_buff)		return -ENOMEM;	if (hw->eeprom.type == e1000_eeprom_spi)		ret_val = e1000_read_eeprom(hw, first_word,					    last_word - first_word + 1,					    eeprom_buff);	else {		for (i = 0; i < last_word - first_word + 1; i++)			if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1,							&eeprom_buff[i])))				break;	}	/* Device's eeprom is always little-endian, word addressable */	for (i = 0; i < last_word - first_word + 1; i++)		le16_to_cpus(&eeprom_buff[i]);	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),			eeprom->len);	kfree(eeprom_buff);	return ret_val;}static inte1000_set_eeprom(struct net_device *netdev,                      struct ethtool_eeprom *eeprom, uint8_t *bytes){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	uint16_t *eeprom_buff;	void *ptr;	int max_len, first_word, last_word, ret_val = 0;	uint16_t i;	if (eeprom->len == 0)		return -EOPNOTSUPP;	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))		return -EFAULT;	max_len = hw->eeprom.word_size * 2;	first_word = eeprom->offset >> 1;	last_word = (eeprom->offset + eeprom->len - 1) >> 1;	eeprom_buff = kmalloc(max_len, GFP_KERNEL);	if (!eeprom_buff)		return -ENOMEM;	ptr = (void *)eeprom_buff;	if (eeprom->offset & 1) {		/* need read/modify/write of first changed EEPROM word */		/* only the second byte of the word is being modified */		ret_val = e1000_read_eeprom(hw, first_word, 1,					    &eeprom_buff[0]);		ptr++;	}	if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {		/* need read/modify/write of last changed EEPROM word */		/* only the first byte of the word is being modified */		ret_val = e1000_read_eeprom(hw, last_word, 1,		                  &eeprom_buff[last_word - first_word]);	}	/* Device's eeprom is always little-endian, word addressable */	for (i = 0; i < last_word - first_word + 1; i++)		le16_to_cpus(&eeprom_buff[i]);	memcpy(ptr, bytes, eeprom->len);	for (i = 0; i < last_word - first_word + 1; i++)		eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);	ret_val = e1000_write_eeprom(hw, first_word,				     last_word - first_word + 1, eeprom_buff);	/* Update the checksum over the first part of the EEPROM if needed	 * and flush shadow RAM for 82573 conrollers */	if ((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||				(hw->mac_type == e1000_82573)))		e1000_update_eeprom_checksum(hw);	kfree(eeprom_buff);	return ret_val;}static voide1000_get_drvinfo(struct net_device *netdev,                       struct ethtool_drvinfo *drvinfo){	struct e1000_adapter *adapter = netdev_priv(netdev);	char firmware_version[32];	uint16_t eeprom_data;	strncpy(drvinfo->driver,  e1000_driver_name, 32);	strncpy(drvinfo->version, e1000_driver_version, 32);	/* EEPROM image version # is reported as firmware version # for	 * 8257{1|2|3} controllers */	e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);	switch (adapter->hw.mac_type) {	case e1000_82571:	case e1000_82572:	case e1000_82573:	case e1000_80003es2lan:	case e1000_ich8lan:		sprintf(firmware_version, "%d.%d-%d",			(eeprom_data & 0xF000) >> 12,			(eeprom_data & 0x0FF0) >> 4,			eeprom_data & 0x000F);		break;	default:		sprintf(firmware_version, "N/A");	}	strncpy(drvinfo->fw_version, firmware_version, 32);	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);	drvinfo->n_stats = E1000_STATS_LEN;	drvinfo->testinfo_len = E1000_TEST_LEN;	drvinfo->regdump_len = e1000_get_regs_len(netdev);	drvinfo->eedump_len = e1000_get_eeprom_len(netdev);}static voide1000_get_ringparam(struct net_device *netdev,                    struct ethtool_ringparam *ring){	struct e1000_adapter *adapter = netdev_priv(netdev);	e1000_mac_type mac_type = adapter->hw.mac_type;	struct e1000_tx_ring *txdr = adapter->tx_ring;	struct e1000_rx_ring *rxdr = adapter->rx_ring;	ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :		E1000_MAX_82544_RXD;	ring->tx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_TXD :		E1000_MAX_82544_TXD;	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;}static inte1000_set_ringparam(struct net_device *netdev,                    struct ethtool_ringparam *ring){	struct e1000_adapter *adapter = netdev_priv(netdev);	e1000_mac_type mac_type = adapter->hw.mac_type;	struct e1000_tx_ring *txdr, *tx_old, *tx_new;	struct e1000_rx_ring *rxdr, *rx_old, *rx_new;	int i, err, tx_ring_size, rx_ring_size;	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))		return -EINVAL;	tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;	rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))		msleep(1);	if (netif_running(adapter->netdev))		e1000_down(adapter);	tx_old = adapter->tx_ring;	rx_old = adapter->rx_ring;	adapter->tx_ring = kmalloc(tx_ring_size, GFP_KERNEL);	if (!adapter->tx_ring) {		err = -ENOMEM;		goto err_setup_rx;	}	memset(adapter->tx_ring, 0, tx_ring_size);	adapter->rx_ring = kmalloc(rx_ring_size, GFP_KERNEL);	if (!adapter->rx_ring) {		kfree(adapter->tx_ring);		err = -ENOMEM;		goto err_setup_rx;	}	memset(adapter->rx_ring, 0, rx_ring_size);	txdr = adapter->tx_ring;	rxdr = adapter->rx_ring;	rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);	rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?		E1000_MAX_RXD : E1000_MAX_82544_RXD));	E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);	txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);	txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?		E1000_MAX_TXD : E1000_MAX_82544_TXD));	E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);	for (i = 0; i < adapter->num_tx_queues; i++)		txdr[i].count = txdr->count;	for (i = 0; i < adapter->num_rx_queues; i++)		rxdr[i].count = rxdr->count;	if (netif_running(adapter->netdev)) {		/* Try to get new resources before deleting old */		if ((err = e1000_setup_all_rx_resources(adapter)))			goto err_setup_rx;		if ((err = e1000_setup_all_tx_resources(adapter)))			goto err_setup_tx;		/* save the new, restore the old in order to free it,		 * then restore the new back again */		rx_new = adapter->rx_ring;		tx_new = adapter->tx_ring;		adapter->rx_ring = rx_old;		adapter->tx_ring = tx_old;		e1000_free_all_rx_resources(adapter);		e1000_free_all_tx_resources(adapter);		kfree(tx_old);		kfree(rx_old);		adapter->rx_ring = rx_new;		adapter->tx_ring = tx_new;		if ((err = e1000_up(adapter)))			goto err_setup;	}	clear_bit(__E1000_RESETTING, &adapter->flags);	return 0;err_setup_tx:	e1000_free_all_rx_resources(adapter);err_setup_rx:	adapter->rx_ring = rx_old;	adapter->tx_ring = tx_old;	e1000_up(adapter);err_setup:	clear_bit(__E1000_RESETTING, &adapter->flags);	return err;}#define REG_PATTERN_TEST(R, M, W)                                              \{                                                                              \	uint32_t pat, value;                                                   \	uint32_t test[] =                                                      \		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};              \	for (pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) {              \		E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W));             \		value = E1000_READ_REG(&adapter->hw, R);                       \		if (value != (test[pat] & W & M)) {                             \			DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \			        "0x%08X expected 0x%08X\n",                    \			        E1000_##R, value, (test[pat] & W & M));        \			*data = (adapter->hw.mac_type < e1000_82543) ?         \				E1000_82542_##R : E1000_##R;                   \			return 1;                                              \		}                                                              \	}                                                                      \}#define REG_SET_AND_CHECK(R, M, W)                                             \{                                                                              \	uint32_t value;                                                        \	E1000_WRITE_REG(&adapter->hw, R, W & M);                               \	value = E1000_READ_REG(&adapter->hw, R);                               \	if ((W & M) != (value & M)) {                                          \		DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\		        "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \		*data = (adapter->hw.mac_type < e1000_82543) ?                 \			E1000_82542_##R : E1000_##R;                           \		return 1;                                                      \	}                                                                      \}static inte1000_reg_test(struct e1000_adapter *adapter, uint64_t *data){	uint32_t value, before, after;	uint32_t i, toggle;	/* The status register is Read Only, so a write should fail.	 * Some bits that get toggled are ignored.	 */	switch (adapter->hw.mac_type) {	/* there are several bits on newer hardware that are r/w */	case e1000_82571:	case e1000_82572:	case e1000_80003es2lan:		toggle = 0x7FFFF3FF;		break;	case e1000_82573:	case e1000_ich8lan:		toggle = 0x7FFFF033;		break;	default:		toggle = 0xFFFFF833;		break;	}	before = E1000_READ_REG(&adapter->hw, STATUS);	value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);	E1000_WRITE_REG(&adapter->hw, STATUS, toggle);	after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;	if (value != after) {		DPRINTK(DRV, ERR, "failed STATUS register test got: "		        "0x%08X expected: 0x%08X\n", after, value);		*data = 1;		return 1;	}	/* restore previous status */	E1000_WRITE_REG(&adapter->hw, STATUS, before);	if (adapter->hw.mac_type != e1000_ich8lan) {		REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);		REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);		REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);		REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);	}	REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);	REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8);	REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF);	REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);	REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);	before = (adapter->hw.mac_type == e1000_ich8lan ?			0x06C3B33E : 0x06DFB3FE);	REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);	REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);	if (adapter->hw.mac_type >= e1000_82543) {		REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);		REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);		if (adapter->hw.mac_type != e1000_ich8lan)			REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);		REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);		REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);		value = (adapter->hw.mac_type == e1000_ich8lan ?				E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);		for (i = 0; i < value; i++) {			REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,					 0xFFFFFFFF);		}	} else {		REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF);		REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF);		REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF);		REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF);	}	value = (adapter->hw.mac_type == e1000_ich8lan ?			E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);	for (i = 0; i < value; i++)		REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);	*data = 0;	return 0;}static inte1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data){	uint16_t temp;	uint16_t checksum = 0;	uint16_t i;	*data = 0;	/* Read and add up the contents of the EEPROM */	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {		if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {			*data = 1;			break;		}		checksum += temp;	}	/* If Checksum is not Correct return error else test passed */	if ((checksum != (uint16_t) EEPROM_SUM) && !(*data))		*data = 2;	return *data;}static irqreturn_te1000_test_intr(int irq,		void *data,		struct pt_regs *regs){	struct net_device *netdev = (struct net_device *) data;	struct e1000_adapter *adapter = netdev_priv(netdev);	adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR);	return IRQ_HANDLED;}static inte1000_intr_test(struct e1000_adapter *adapter, uint64_t *data){	struct net_device *netdev = adapter->netdev;	uint32_t mask, i=0, shared_int = TRUE;	uint32_t irq = adapter->pdev->irq;	*data = 0;	/* NOTE: we don't test MSI interrupts here, yet */	/* Hook up test interrupt handler just for this test */	if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,	                 netdev))		shared_int = FALSE;	else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,			      netdev->name, netdev)){		*data = 1;		return -1;	}	DPRINTK(HW, INFO, "testing %s interrupt\n",	        (shared_int ? "shared" : "unshared"));	/* Disable all the interrupts */	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);	msec_delay(10);	/* Test each interrupt */	for (; i < 10; i++) {		if (adapter->hw.mac_type == e1000_ich8lan && i == 8)			continue;		/* Interrupt to test */		mask = 1 << i;		if (!shared_int) {			/* Disable the interrupt to be reported in			 * the cause register and then force the same			 * interrupt and see if one gets posted.  If			 * an interrupt was posted to the bus, the			 * test failed.			 */			adapter->test_icr = 0;			E1000_WRITE_REG(&adapter->hw, IMC, mask);			E1000_WRITE_REG(&adapter->hw, ICS, mask);			msec_delay(10);			if (adapter->test_icr & mask) {				*data = 3;				break;			}		}		/* Enable the interrupt to be reported in		 * the cause register and then force the same		 * interrupt and see if one gets posted.  If		 * an interrupt was not posted to the bus, the		 * test failed.		 */		adapter->test_icr = 0;		E1000_WRITE_REG(&adapter->hw, IMS, mask);		E1000_WRITE_REG(&adapter->hw, ICS, mask);		msec_delay(10);		if (!(adapter->test_icr & mask)) {			*data = 4;			break;		}		if (!shared_int) {			/* Disable the other interrupts to be reported in			 * the cause register and then force the other			 * interrupts and see if any get posted.  If			 * an interrupt was posted to the bus, the			 * test failed.			 */			adapter->test_icr = 0;			E1000_WRITE_REG(&adapter->hw, IMC, ~mask & 0x00007FFF);			E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);			msec_delay(10);			if (adapter->test_icr) {				*data = 5;

⌨️ 快捷键说明

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