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

📄 ethtool.c

📁 DELL755 Intel 网卡驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	struct e1000_hw *hw = &adapter->hw;	u16 *eeprom_buff;	int first_word;	int last_word;	int ret_val = 0;	u16 i;	if (eeprom->len == 0)		return -EINVAL;	eeprom->magic = adapter->pdev->vendor | (adapter->pdev->device << 16);	first_word = eeprom->offset >> 1;	last_word = (eeprom->offset + eeprom->len - 1) >> 1;	eeprom_buff = kmalloc(sizeof(u16) *			(last_word - first_word + 1), GFP_KERNEL);	if (!eeprom_buff)		return -ENOMEM;	if (hw->nvm.type == e1000_nvm_eeprom_spi) {		ret_val = hw->nvm.ops.read(hw, first_word,		                           last_word - first_word + 1,		                           eeprom_buff);	} else {		for (i = 0; i < last_word - first_word + 1; i++) {			ret_val = hw->nvm.ops.read(hw, first_word + i, 1,			                           &eeprom_buff[i]);			if (ret_val)				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, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);	kfree(eeprom_buff);	return ret_val;}static int e1000_set_eeprom(struct net_device *netdev,			    struct ethtool_eeprom *eeprom, u8 *bytes){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	u16 *eeprom_buff;	void *ptr;	int max_len;	int first_word;	int last_word;	int ret_val = 0;	u16 i;	if (eeprom->len == 0)		return -EOPNOTSUPP;	if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))		return -EFAULT;	max_len = hw->nvm.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 = hw->nvm.ops.read(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 = hw->nvm.ops.read(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 = hw->nvm.ops.write(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 controllers	 */	if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG) ||			       (hw->mac.type == e1000_82574) ||			       (hw->mac.type == e1000_82573)))		hw->nvm.ops.update(hw);	kfree(eeprom_buff);	return ret_val;}static void e1000_get_drvinfo(struct net_device *netdev,			      struct ethtool_drvinfo *drvinfo){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	char firmware_version[32];	u16 eeprom_data;	strncpy(drvinfo->driver,  e1000e_driver_name, 32);	strncpy(drvinfo->version, e1000e_driver_version, 32);	/*	 * EEPROM image version # is reported as firmware version # for	 * PCI-E controllers	 */	hw->nvm.ops.read(&adapter->hw, 5, 1, &eeprom_data);	sprintf(firmware_version, "%d.%d-%d",		(eeprom_data & 0xF000) >> 12,		(eeprom_data & 0x0FF0) >> 4,		eeprom_data & 0x000F);	strncpy(drvinfo->fw_version, firmware_version, 32);	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);	drvinfo->regdump_len = e1000_get_regs_len(netdev);	drvinfo->eedump_len = e1000_get_eeprom_len(netdev);}static void e1000_get_ringparam(struct net_device *netdev,				struct ethtool_ringparam *ring){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_ring *tx_ring = adapter->tx_ring;	struct e1000_ring *rx_ring = adapter->rx_ring;	ring->rx_max_pending = E1000_MAX_RXD;	ring->tx_max_pending = E1000_MAX_TXD;	ring->rx_mini_max_pending = 0;	ring->rx_jumbo_max_pending = 0;	ring->rx_pending = rx_ring->count;	ring->tx_pending = tx_ring->count;	ring->rx_mini_pending = 0;	ring->rx_jumbo_pending = 0;}static int e1000_set_ringparam(struct net_device *netdev,			       struct ethtool_ringparam *ring){	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_ring *tx_ring, *tx_old;	struct e1000_ring *rx_ring, *rx_old;	int err;	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))		return -EINVAL;	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))		msleep(1);	if (netif_running(adapter->netdev))		e1000_down(adapter);	tx_old = adapter->tx_ring;	rx_old = adapter->rx_ring;	err = -ENOMEM;	tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);	if (!tx_ring)		goto err_alloc_tx;	/*	 * use a memcpy to save any previously configured	 * items like napi structs from having to be	 * reinitialized	 */	memcpy(tx_ring, tx_old, sizeof(struct e1000_ring));	rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);	if (!rx_ring)		goto err_alloc_rx;	memcpy(rx_ring, rx_old, sizeof(struct e1000_ring));	adapter->tx_ring = tx_ring;	adapter->rx_ring = rx_ring;	rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD);	rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD));	rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);	tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD);	tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD));	tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);	if (netif_running(adapter->netdev)) {		/* Try to get new resources before deleting old */		err = e1000_setup_rx_resources(adapter);		if (err)			goto err_setup_rx;		err = e1000_setup_tx_resources(adapter);		if (err)			goto err_setup_tx;		/*		 * restore the old in order to free it,		 * then add in the new		 */		adapter->rx_ring = rx_old;		adapter->tx_ring = tx_old;		e1000_free_rx_resources(adapter);		e1000_free_tx_resources(adapter);		kfree(tx_old);		kfree(rx_old);		adapter->rx_ring = rx_ring;		adapter->tx_ring = tx_ring;		err = e1000_up(adapter);		if (err)			goto err_setup;	}	clear_bit(__E1000_RESETTING, &adapter->state);	return 0;err_setup_tx:	e1000_free_rx_resources(adapter);err_setup_rx:	adapter->rx_ring = rx_old;	adapter->tx_ring = tx_old;	kfree(rx_ring);err_alloc_rx:	kfree(tx_ring);err_alloc_tx:	e1000_up(adapter);err_setup:	clear_bit(__E1000_RESETTING, &adapter->state);	return err;}static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,			     int reg, int offset, u32 mask, u32 write){	u32 pat, val;	static const u32 test[] =		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};	for (pat = 0; pat < ARRAY_SIZE(test); pat++) {		E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset,		                      (test[pat] & write));		val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);		if (val != (test[pat] & write & mask)) {			e_err("pattern test reg %04X failed: got "			      "0x%08X expected 0x%08X\n",			      reg + offset,			      val, (test[pat] & write & mask));			*data = reg;			return 1;		}	}	return 0;}static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,			      int reg, u32 mask, u32 write){	u32 val;	__ew32(&adapter->hw, reg, write & mask);	val = __er32(&adapter->hw, reg);	if ((write & mask) != (val & mask)) {		e_err("set/check reg %04X test failed: got 0x%08X"		      "expected 0x%08X\n", reg, (val & mask), (write & mask));		*data = reg;		return 1;	}	return 0;}#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write)                       \	do {                                                                   \		if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \			return 1;                                              \	} while (0)#define REG_PATTERN_TEST(reg, mask, write)                                     \	REG_PATTERN_TEST_ARRAY(reg, 0, mask, write)#define REG_SET_AND_CHECK(reg, mask, write)                                    \	do {                                                                   \		if (reg_set_and_check(adapter, data, reg, mask, write))        \			return 1;                                              \	} while (0)static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data){	struct e1000_hw *hw = &adapter->hw;	struct e1000_mac_info *mac = &adapter->hw.mac;	u32 value;	u32 before;	u32 after;	u32 i;	u32 toggle;	/*	 * The status register is Read Only, so a write should fail.	 * Some bits that get toggled are ignored.	 */	switch (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_82574:	case e1000_ich8lan:	case e1000_ich9lan:	case e1000_ich10lan:		toggle = 0x7FFFF033;		break;	default:		toggle = 0xFFFFF833;		break;	}	before = er32(STATUS);	value = (er32(STATUS) & toggle);	ew32(STATUS, toggle);	after = er32(STATUS) & toggle;	if (value != after) {		e_err("failed STATUS register test got: "			 "0x%08X expected: 0x%08X\n", after, value);		*data = 1;		return 1;	}	/* restore previous status */	ew32(STATUS, before);	if (!(adapter->flags & FLAG_IS_ICH)) {		REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF);		REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF);		REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF);		REG_PATTERN_TEST(E1000_VET, 0x0000FFFF, 0xFFFFFFFF);	}	REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF);	REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8);	REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF);	REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF);	REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF);	REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000);	before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE);	REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB);	REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000);	REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF);	REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF);	if (!(adapter->flags & FLAG_IS_ICH))		REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF);	REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF);	REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF);	for (i = 0; i < mac->rar_entry_count; i++)		REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1),				       ((mac->type == e1000_ich10lan) ?		                           0x8007FFFF : 0x8003FFFF),		                       0xFFFFFFFF);	for (i = 0; i < mac->mta_reg_count; i++)		REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);	*data = 0;	return 0;}static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data){	struct e1000_hw *hw = &adapter->hw;	u16 temp;	u16 checksum = 0;	u16 i;	*data = 0;	/* Read and add up the contents of the EEPROM */	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {		if ((hw->nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) {			*data = 1;			break;		}		checksum += temp;	}	/* If Checksum is not Correct return error else test passed */	if ((checksum != (u16) NVM_SUM) && !(*data))		*data = 2;	return *data;}static irqreturn_t e1000_test_intr(int irq, void *data){	struct net_device *netdev = (struct net_device *) data;	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	adapter->test_icr |= er32(ICR);	return IRQ_HANDLED;}static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data){	struct net_device *netdev = adapter->netdev;	struct e1000_hw *hw = &adapter->hw;	u32 mask;	u32 shared_int = 1;	u32 irq = adapter->pdev->irq;	int i;#ifdef CONFIG_E1000E_MSIX	int ret_val = 0;	int int_mode = E1000E_INT_MODE_LEGACY;#endif	*data = 0;	/* NOTE: we don't test MSI/MSI-X interrupts here, yet */#ifdef CONFIG_E1000E_MSIX	if (adapter->int_mode == E1000E_INT_MODE_MSIX) {		int_mode = adapter->int_mode;		e1000_reset_interrupt_capability(adapter);		adapter->int_mode = E1000E_INT_MODE_LEGACY;		e1000_set_interrupt_capability(adapter);	}#endif	/* Hook up test interrupt handler just for this test */	if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,			 netdev)) {		shared_int = 0;	} else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,		 netdev->name, netdev)) {		*data = 1;#ifdef CONFIG_E1000E_MSIX		ret_val = -1;		goto out;#else		return -1;#endif	}	e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared"));	/* Disable all the interrupts */	ew32(IMC, 0xFFFFFFFF);	msleep(10);	/* Test each interrupt */	for (i = 0; i < 10; i++) {		/* Interrupt to test */		mask = 1 << i;		if (adapter->flags & FLAG_IS_ICH) {			switch (mask) {			case E1000_ICR_RXSEQ:				continue;			case 0x00000100:				if (adapter->hw.mac.type == e1000_ich8lan ||				    adapter->hw.mac.type == e1000_ich9lan)					continue;				break;			default:				break;			}		}		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;			ew32(IMC, mask);			ew32(ICS, mask);			msleep(10);			if (adapter->test_icr & mask) {				*data = 3;				break;			}		}		/*		 * Enable the interrupt to be reported in

⌨️ 快捷键说明

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