diff options
-rw-r--r-- | drivers/net/e1000e/82571.c | 4 | ||||
-rw-r--r-- | drivers/net/e1000e/defines.h | 1 | ||||
-rw-r--r-- | drivers/net/e1000e/hw.h | 1 | ||||
-rw-r--r-- | drivers/net/e1000e/lib.c | 39 |
4 files changed, 43 insertions, 2 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 14141a55eaa..b6401abc17d 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -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; } diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index b32ed45b4b3..f2175ea46b8 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -557,6 +557,7 @@ #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 */ diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 64515789fd4..1bb20521df0 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -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 { diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 0bdeca30c75..16f35fadb74 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -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++) |