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 /drivers/net/e1000/e1000_main.c | |
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>
Diffstat (limited to 'drivers/net/e1000/e1000_main.c')
-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 | ||