e1000e: alternate MAC address support
authorBill Hayes <bill.hayes@hp.com>
Wed, 31 Oct 2007 22:21:52 +0000 (15:21 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 23:03:42 +0000 (15:03 -0800)
Port alternate MAC address support from the sourceforge
e1000 driver to the upstream e1000e driver.

Signed-off-by: Bill Hayes <bill.hayes@hp.com>
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/e1000e/82571.c
drivers/net/e1000e/defines.h
drivers/net/e1000e/hw.h
drivers/net/e1000e/lib.c

index 14141a5..b6401ab 100644 (file)
@@ -752,6 +752,10 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
        ew32(IMC, 0xffffffff);
        icr = er32(ICR);
 
+       if (hw->mac.type == e1000_82571 &&
+               hw->dev_spec.e82571.alt_mac_addr_is_present)
+                       e1000e_set_laa_state_82571(hw, true);
+
        return 0;
 }
 
index b32ed45..f2175ea 100644 (file)
 #define NVM_INIT_3GIO_3            0x001A
 #define NVM_INIT_CONTROL3_PORT_A   0x0024
 #define NVM_CFG                    0x0012
+#define NVM_ALT_MAC_ADDR_PTR       0x0037
 #define NVM_CHECKSUM_REG           0x003F
 
 #define E1000_NVM_CFG_DONE_PORT_0  0x40000 /* MNG config cycle done */
index 6451578..1bb2052 100644 (file)
@@ -816,6 +816,7 @@ struct e1000_bus_info {
 
 struct e1000_dev_spec_82571 {
        bool laa_is_present;
+       bool alt_mac_addr_is_present;
 };
 
 struct e1000_shadow_ram {
index 0bdeca3..16f35fa 100644 (file)
@@ -2059,9 +2059,44 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
 {
        s32 ret_val;
        u16 offset, nvm_data, i;
+       u16 mac_addr_offset = 0;
+
+       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_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
+                                               &mac_addr_offset);
+               if (ret_val) {
+                       hw_dbg(hw, "NVM Read Error\n");
+                       return ret_val;
+               }
+               if (mac_addr_offset == 0xFFFF)
+                       mac_addr_offset = 0;
+
+               if (mac_addr_offset) {
+                       if (hw->bus.func == E1000_FUNC_1)
+                               mac_addr_offset += ETH_ALEN/sizeof(u16);
+
+                       /* make sure we have a valid mac address here
+                        * before using it */
+                       ret_val = e1000_read_nvm(hw, mac_addr_offset, 1,
+                                                &nvm_data);
+                       if (ret_val) {
+                               hw_dbg(hw, "NVM Read Error\n");
+                               return ret_val;
+                       }
+                       if (nvm_data & 0x0001)
+                               mac_addr_offset = 0;
+               }
+
+               if (mac_addr_offset)
+                       hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
+       }
 
        for (i = 0; i < ETH_ALEN; i += 2) {
-               offset = i >> 1;
+               offset = mac_addr_offset + (i >> 1);
                ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
                if (ret_val) {
                        hw_dbg(hw, "NVM Read Error\n");
@@ -2072,7 +2107,7 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
        }
 
        /* Flip last bit of mac address if we're on second port */
-       if (hw->bus.func == E1000_FUNC_1)
+       if (!mac_addr_offset && hw->bus.func == E1000_FUNC_1)
                hw->mac.perm_addr[5] ^= 1;
 
        for (i = 0; i < ETH_ALEN; i++)