|
@@ -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++)
|