Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 67b3c27c authored by Auke Kok's avatar Auke Kok Committed by David S. Miller
Browse files

e1000: Dump the eeprom when a user encounters a bad checksum



To help supporting users with a bad eeprom checksum, dump the
eeprom info when such a situation is encountered by a user.

Signed-off-by: default avatarAuke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 8b32e63d
Loading
Loading
Loading
Loading
+74 −11
Original line number Diff line number Diff line
@@ -817,6 +817,64 @@ e1000_reset(struct e1000_adapter *adapter)
	e1000_release_manageability(adapter);
}

/**
 *  Dump the eeprom for users having checksum issues
 **/
void e1000_dump_eeprom(struct e1000_adapter *adapter)
{
	struct net_device *netdev = adapter->netdev;
	struct ethtool_eeprom eeprom;
	const struct ethtool_ops *ops = netdev->ethtool_ops;
	u8 *data;
	int i;
	u16 csum_old, csum_new = 0;

	eeprom.len = ops->get_eeprom_len(netdev);
	eeprom.offset = 0;

	data = kmalloc(eeprom.len, GFP_KERNEL);
	if (!data) {
		printk(KERN_ERR "Unable to allocate memory to dump EEPROM"
		       " data\n");
		return;
	}

	ops->get_eeprom(netdev, &eeprom, data);

	csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
		   (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
	for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2)
		csum_new += data[i] + (data[i + 1] << 8);
	csum_new = EEPROM_SUM - csum_new;

	printk(KERN_ERR "/*********************/\n");
	printk(KERN_ERR "Current EEPROM Checksum : 0x%04x\n", csum_old);
	printk(KERN_ERR "Calculated              : 0x%04x\n", csum_new);

	printk(KERN_ERR "Offset    Values\n");
	printk(KERN_ERR "========  ======\n");
	print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0);

	printk(KERN_ERR "Include this output when contacting your support "
	       "provider.\n");
	printk(KERN_ERR "This is not a software error! Something bad "
	       "happened to your hardware or\n");
	printk(KERN_ERR "EEPROM image. Ignoring this "
	       "problem could result in further problems,\n");
	printk(KERN_ERR "possibly loss of data, corruption or system hangs!\n");
	printk(KERN_ERR "The MAC Address will be reset to 00:00:00:00:00:00, "
	       "which is invalid\n");
	printk(KERN_ERR "and requires you to set the proper MAC "
	       "address manually before continuing\n");
	printk(KERN_ERR "to enable this network device.\n");
	printk(KERN_ERR "Please inspect the EEPROM dump and report the issue "
	       "to your hardware vendor\n");
	printk(KERN_ERR "or Intel Customer Support: linux-nics@intel.com\n");
	printk(KERN_ERR "/*********************/\n");

	kfree(data);
}

/**
 * e1000_probe - Device Initialization Routine
 * @pdev: PCI device information struct
@@ -968,7 +1026,6 @@ e1000_probe(struct pci_dev *pdev,
	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);

	/* initialize eeprom parameters */

	if (e1000_init_eeprom_params(&adapter->hw)) {
		E1000_ERR("EEPROM initialization failed\n");
		goto err_eeprom;
@@ -980,23 +1037,29 @@ e1000_probe(struct pci_dev *pdev,
	e1000_reset_hw(&adapter->hw);

	/* make sure the EEPROM is good */

	if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
		DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
		goto err_eeprom;
	}

		e1000_dump_eeprom(adapter);
		/*
		 * set MAC address to all zeroes to invalidate and temporary
		 * disable this device for the user. This blocks regular
		 * traffic while still permitting ethtool ioctls from reaching
		 * the hardware as well as allowing the user to run the
		 * interface after manually setting a hw addr using
		 * `ip set address`
		 */
		memset(adapter->hw.mac_addr, 0, netdev->addr_len);
	} else {
		/* copy the MAC address out of the EEPROM */

		if (e1000_read_mac_addr(&adapter->hw))
			DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
	}
	/* don't block initalization here due to bad MAC address */
	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);

	if (!is_valid_ether_addr(netdev->perm_addr)) {
	if (!is_valid_ether_addr(netdev->perm_addr))
		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
		goto err_eeprom;
	}

	e1000_get_bus_info(&adapter->hw);