diff options
| author | Auke Kok <auke-jan.h.kok@intel.com> | 2007-12-17 16:50:23 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:07:18 -0500 |
| commit | 67b3c27c8a8d8f81ffc3fe0afc0d805d66744d18 (patch) | |
| tree | d202c7fd4e723f63ab43c3be9b9935d48d1dc9b9 | |
| parent | 8b32e63d48d43f3843222ca66fecd45ff2a74147 (diff) | |
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: Auke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/net/e1000/e1000_main.c | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5b129964e832..7f5b2ae70d5d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -818,6 +818,64 @@ e1000_reset(struct e1000_adapter *adapter) | |||
| 818 | } | 818 | } |
| 819 | 819 | ||
| 820 | /** | 820 | /** |
| 821 | * Dump the eeprom for users having checksum issues | ||
| 822 | **/ | ||
| 823 | void e1000_dump_eeprom(struct e1000_adapter *adapter) | ||
| 824 | { | ||
| 825 | struct net_device *netdev = adapter->netdev; | ||
| 826 | struct ethtool_eeprom eeprom; | ||
| 827 | const struct ethtool_ops *ops = netdev->ethtool_ops; | ||
| 828 | u8 *data; | ||
| 829 | int i; | ||
| 830 | u16 csum_old, csum_new = 0; | ||
| 831 | |||
| 832 | eeprom.len = ops->get_eeprom_len(netdev); | ||
| 833 | eeprom.offset = 0; | ||
| 834 | |||
| 835 | data = kmalloc(eeprom.len, GFP_KERNEL); | ||
| 836 | if (!data) { | ||
| 837 | printk(KERN_ERR "Unable to allocate memory to dump EEPROM" | ||
| 838 | " data\n"); | ||
| 839 | return; | ||
| 840 | } | ||
| 841 | |||
| 842 | ops->get_eeprom(netdev, &eeprom, data); | ||
| 843 | |||
| 844 | csum_old = (data[EEPROM_CHECKSUM_REG * 2]) + | ||
| 845 | (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8); | ||
| 846 | for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2) | ||
| 847 | csum_new += data[i] + (data[i + 1] << 8); | ||
| 848 | csum_new = EEPROM_SUM - csum_new; | ||
| 849 | |||
| 850 | printk(KERN_ERR "/*********************/\n"); | ||
| 851 | printk(KERN_ERR "Current EEPROM Checksum : 0x%04x\n", csum_old); | ||
| 852 | printk(KERN_ERR "Calculated : 0x%04x\n", csum_new); | ||
| 853 | |||
| 854 | printk(KERN_ERR "Offset Values\n"); | ||
| 855 | printk(KERN_ERR "======== ======\n"); | ||
| 856 | print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0); | ||
| 857 | |||
| 858 | printk(KERN_ERR "Include this output when contacting your support " | ||
| 859 | "provider.\n"); | ||
| 860 | printk(KERN_ERR "This is not a software error! Something bad " | ||
| 861 | "happened to your hardware or\n"); | ||
| 862 | printk(KERN_ERR "EEPROM image. Ignoring this " | ||
| 863 | "problem could result in further problems,\n"); | ||
| 864 | printk(KERN_ERR "possibly loss of data, corruption or system hangs!\n"); | ||
| 865 | printk(KERN_ERR "The MAC Address will be reset to 00:00:00:00:00:00, " | ||
| 866 | "which is invalid\n"); | ||
| 867 | printk(KERN_ERR "and requires you to set the proper MAC " | ||
| 868 | "address manually before continuing\n"); | ||
| 869 | printk(KERN_ERR "to enable this network device.\n"); | ||
| 870 | printk(KERN_ERR "Please inspect the EEPROM dump and report the issue " | ||
| 871 | "to your hardware vendor\n"); | ||
| 872 | printk(KERN_ERR "or Intel Customer Support: linux-nics@intel.com\n"); | ||
| 873 | printk(KERN_ERR "/*********************/\n"); | ||
| 874 | |||
| 875 | kfree(data); | ||
| 876 | } | ||
| 877 | |||
| 878 | /** | ||
| 821 | * e1000_probe - Device Initialization Routine | 879 | * e1000_probe - Device Initialization Routine |
| 822 | * @pdev: PCI device information struct | 880 | * @pdev: PCI device information struct |
| 823 | * @ent: entry in e1000_pci_tbl | 881 | * @ent: entry in e1000_pci_tbl |
| @@ -968,7 +1026,6 @@ e1000_probe(struct pci_dev *pdev, | |||
| 968 | adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw); | 1026 | adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw); |
| 969 | 1027 | ||
| 970 | /* initialize eeprom parameters */ | 1028 | /* initialize eeprom parameters */ |
| 971 | |||
| 972 | if (e1000_init_eeprom_params(&adapter->hw)) { | 1029 | if (e1000_init_eeprom_params(&adapter->hw)) { |
| 973 | E1000_ERR("EEPROM initialization failed\n"); | 1030 | E1000_ERR("EEPROM initialization failed\n"); |
| 974 | goto err_eeprom; | 1031 | goto err_eeprom; |
| @@ -980,23 +1037,29 @@ e1000_probe(struct pci_dev *pdev, | |||
| 980 | e1000_reset_hw(&adapter->hw); | 1037 | e1000_reset_hw(&adapter->hw); |
| 981 | 1038 | ||
| 982 | /* make sure the EEPROM is good */ | 1039 | /* make sure the EEPROM is good */ |
| 983 | |||
| 984 | if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) { | 1040 | if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) { |
| 985 | DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); | 1041 | DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); |
| 986 | goto err_eeprom; | 1042 | e1000_dump_eeprom(adapter); |
| 1043 | /* | ||
| 1044 | * set MAC address to all zeroes to invalidate and temporary | ||
| 1045 | * disable this device for the user. This blocks regular | ||
| 1046 | * traffic while still permitting ethtool ioctls from reaching | ||
| 1047 | * the hardware as well as allowing the user to run the | ||
| 1048 | * interface after manually setting a hw addr using | ||
| 1049 | * `ip set address` | ||
| 1050 | */ | ||
| 1051 | memset(adapter->hw.mac_addr, 0, netdev->addr_len); | ||
| 1052 | } else { | ||
| 1053 | /* copy the MAC address out of the EEPROM */ | ||
| 1054 | if (e1000_read_mac_addr(&adapter->hw)) | ||
| 1055 | DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); | ||
| 987 | } | 1056 | } |
| 988 | 1057 | /* don't block initalization here due to bad MAC address */ | |
| 989 | /* copy the MAC address out of the EEPROM */ | ||
| 990 | |||
| 991 | if (e1000_read_mac_addr(&adapter->hw)) | ||
| 992 | DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); | ||
| 993 | memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); | 1058 | memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); |
| 994 | memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); | 1059 | memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); |
| 995 | 1060 | ||
| 996 | if (!is_valid_ether_addr(netdev->perm_addr)) { | 1061 | if (!is_valid_ether_addr(netdev->perm_addr)) |
| 997 | DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); | 1062 | DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); |
| 998 | goto err_eeprom; | ||
| 999 | } | ||
| 1000 | 1063 | ||
| 1001 | e1000_get_bus_info(&adapter->hw); | 1064 | e1000_get_bus_info(&adapter->hw); |
| 1002 | 1065 | ||
