[e1000] Use the alternate MAC in NVRAM when available
authorAlex Williamson <alex.williamson@hp.com>
Thu, 19 Nov 2009 15:46:30 +0000 (08:46 -0700)
committerMarty Connor <mdc@etherboot.org>
Sun, 22 Nov 2009 12:51:23 +0000 (07:51 -0500)
The 82571 supports an alternate MAC address location in NVRAM.
When this is set, use this for the MAC rather than the default
physical MAC address.

Ported from linux-2.6.git 93ca161027eb6a1761fb674ad7b995aedccf5f6e

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Tested-by: Thomas Miletich <thomas.miletich@gmail.com>
Signed-off-by: Marty Connor <mdc@etherboot.org>
src/drivers/net/e1000/e1000_hw.c
src/drivers/net/e1000/e1000_hw.h

index f90f871..1871dfc 100644 (file)
@@ -728,6 +728,17 @@ e1000_reset_hw(struct e1000_hw *hw)
     /* Clear any pending interrupt events. */
     icr = E1000_READ_REG(hw, ICR);
 
     /* Clear any pending interrupt events. */
     icr = E1000_READ_REG(hw, ICR);
 
+    if (hw->mac_type == e1000_82571 && hw->laa_is_present == TRUE) {
+        /*
+         * Hold a copy of the LAA in RAR[14] This is done so that
+         * between the time RAR[0] gets clobbered and the time it
+         * gets fixed, the actual LAA is in one of the RARs and no
+         * incoming packets directed to this port are dropped.
+         * Eventually the LAA will be in RAR[0] and RAR[14].
+         */
+        e1000_rar_set(hw, hw->mac_addr, E1000_RAR_ENTRIES - 1);
+    }
+
     /* If MWI was previously enabled, reenable it. */
     if (hw->mac_type == e1000_82542_rev2_0) {
         if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
     /* If MWI was previously enabled, reenable it. */
     if (hw->mac_type == e1000_82542_rev2_0) {
         if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
@@ -5774,13 +5785,48 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
 int32_t
 e1000_read_mac_addr(struct e1000_hw * hw)
 {
 int32_t
 e1000_read_mac_addr(struct e1000_hw * hw)
 {
-    uint16_t offset;
+    uint16_t offset, mac_addr_offset = 0;
     uint16_t eeprom_data, i;
     uint16_t eeprom_data, i;
+    int32_t ret_val;
 
     DEBUGFUNC("e1000_read_mac_addr");
 
 
     DEBUGFUNC("e1000_read_mac_addr");
 
+    if (hw->mac_type == e1000_82571) {
+        /* Check for an alternate MAC address.  An alternate MAC
+         * address can be setup by pre-boot software and must be
+         * treated like a permanent address and must override the
+         * actual permanent MAC address.*/
+        ret_val = e1000_read_eeprom(hw, EEPROM_ALT_MAC_ADDR_PTR, 1,
+                                    &mac_addr_offset);
+        if (ret_val) {
+            DEBUGOUT("EEPROM Read Error\n");
+            return -E1000_ERR_EEPROM;
+        }
+        if (mac_addr_offset == 0xFFFF)
+            mac_addr_offset = 0;
+
+        if (mac_addr_offset) {
+            if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+                mac_addr_offset += NODE_ADDRESS_SIZE/sizeof(u16);
+
+                /* make sure we have a valid mac address here
+                 * before using it */
+               ret_val = e1000_read_eeprom(hw, mac_addr_offset, 1,
+                                           &eeprom_data);
+               if (ret_val) {
+                   DEBUGOUT("EEPROM Read Error\n");
+                   return -E1000_ERR_EEPROM;
+               }
+               if (eeprom_data & 0x0001)
+                   mac_addr_offset = 0;
+        }
+
+        if (mac_addr_offset)
+            hw->laa_is_present = TRUE;
+    }
+
     for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
     for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
-        offset = i >> 1;
+        offset = mac_addr_offset + (i >> 1);
         if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
             DEBUGOUT("EEPROM Read Error\n");
             return -E1000_ERR_EEPROM;
         if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
             DEBUGOUT("EEPROM Read Error\n");
             return -E1000_ERR_EEPROM;
@@ -5797,7 +5843,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
     case e1000_82571:
     case e1000_82576:
     case e1000_80003es2lan:
     case e1000_82571:
     case e1000_82576:
     case e1000_80003es2lan:
-        if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+        if (!mac_addr_offset &&
+            E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
             hw->perm_mac_addr[5] ^= 0x01;
         break;
     }
             hw->perm_mac_addr[5] ^= 0x01;
         break;
     }
index 7ecac6c..628b2e3 100644 (file)
@@ -2299,6 +2299,7 @@ struct e1000_host_command_info {
 #define EEPROM_INIT_CONTROL3_PORT_A   0x0024
 #define EEPROM_CFG                    0x0012
 #define EEPROM_FLASH_VERSION          0x0032
 #define EEPROM_INIT_CONTROL3_PORT_A   0x0024
 #define EEPROM_CFG                    0x0012
 #define EEPROM_FLASH_VERSION          0x0032
+#define EEPROM_ALT_MAC_ADDR_PTR       0x0037
 #define EEPROM_CHECKSUM_REG           0x003F
 
 #define E1000_EEPROM_CFG_DONE         0x00040000   /* MNG config cycle done */
 #define EEPROM_CHECKSUM_REG           0x003F
 
 #define E1000_EEPROM_CFG_DONE         0x00040000   /* MNG config cycle done */