Skip to content

Commit

Permalink
e1000: Dump the eeprom when a user encounters a bad checksum
Browse files Browse the repository at this point in the history
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: Auke Kok <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
  • Loading branch information
ahkok authored and davem330 committed Jan 28, 2008
1 parent 8b32e63 commit 67b3c27
Showing 1 changed file with 74 additions and 11 deletions.
85 changes: 74 additions & 11 deletions drivers/net/e1000/e1000_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]\n");
printk(KERN_ERR "/*********************/\n");

kfree(data);
}

/**
* e1000_probe - Device Initialization Routine
* @pdev: PCI device information struct
Expand Down Expand Up @@ -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;
Expand All @@ -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");
}

/* 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);

Expand Down

0 comments on commit 67b3c27

Please sign in to comment.