Commit b4de6c49 authored by Mark Starovoytov's avatar Mark Starovoytov Committed by Jakub Kicinski

net: atlantic: unify MAC generation

This patch unifies invalid MAC address handling with other drivers.

Basically we've switched to using standard APIs (is_valid_ether_addr /
eth_hw_addr_random) where possible.
It's worth noting that some of engineering Aquantia NICs might be
provisioned with a partially zeroed out MAC, which is still invalid,
but not caught by is_valid_ether_addr(), so we've added a special
handling for this case.

Also adding a warning in case of fallback to random MAC, because
this shouldn't be needed on production NICs, they should all be
provisioned with unique MAC.

NB! Default systemd/udevd configuration is 'MACAddressPolicy=persistent'.
    This causes MAC address to be persisted across driver reloads and
    reboots. We had to change it to 'none' for verification purposes.
Signed-off-by: default avatarMark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 097d638c
...@@ -272,6 +272,14 @@ static int aq_nic_hw_prepare(struct aq_nic_s *self) ...@@ -272,6 +272,14 @@ static int aq_nic_hw_prepare(struct aq_nic_s *self)
return err; return err;
} }
static bool aq_nic_is_valid_ether_addr(const u8 *addr)
{
/* Some engineering samples of Aquantia NICs are provisioned with a
* partially populated MAC, which is still invalid.
*/
return !(addr[0] == 0 && addr[1] == 0 && addr[2] == 0);
}
int aq_nic_ndev_register(struct aq_nic_s *self) int aq_nic_ndev_register(struct aq_nic_s *self)
{ {
int err = 0; int err = 0;
...@@ -296,6 +304,12 @@ int aq_nic_ndev_register(struct aq_nic_s *self) ...@@ -296,6 +304,12 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
if (err) if (err)
goto err_exit; goto err_exit;
if (!is_valid_ether_addr(self->ndev->dev_addr) ||
!aq_nic_is_valid_ether_addr(self->ndev->dev_addr)) {
netdev_warn(self->ndev, "MAC is invalid, will use random.");
eth_hw_addr_random(self->ndev);
}
#if defined(AQ_CFG_MAC_ADDR_PERMANENT) #if defined(AQ_CFG_MAC_ADDR_PERMANENT)
{ {
static u8 mac_addr_permanent[] = AQ_CFG_MAC_ADDR_PERMANENT; static u8 mac_addr_permanent[] = AQ_CFG_MAC_ADDR_PERMANENT;
......
...@@ -283,8 +283,6 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) ...@@ -283,8 +283,6 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
u32 mac_addr[2] = { 0 }; u32 mac_addr[2] = { 0 };
int err = 0; int err = 0;
u32 h = 0U;
u32 l = 0U;
if (efuse_addr != 0) { if (efuse_addr != 0) {
err = hw_atl_utils_fw_downld_dwords(self, err = hw_atl_utils_fw_downld_dwords(self,
...@@ -299,26 +297,6 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) ...@@ -299,26 +297,6 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
ether_addr_copy(mac, (u8 *)mac_addr); ether_addr_copy(mac, (u8 *)mac_addr);
if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
unsigned int rnd = 0;
get_random_bytes(&rnd, sizeof(unsigned int));
l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16);
h = 0x8001300EU;
mac[5] = (u8)(0xFFU & l);
l >>= 8;
mac[4] = (u8)(0xFFU & l);
l >>= 8;
mac[3] = (u8)(0xFFU & l);
l >>= 8;
mac[2] = (u8)(0xFFU & l);
mac[1] = (u8)(0xFFU & h);
h >>= 8;
mac[0] = (u8)(0xFFU & h);
}
return err; return err;
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include "aq_hw.h" #include "aq_hw.h"
#include "aq_hw_utils.h"
#include "hw_atl/hw_atl_llh.h" #include "hw_atl/hw_atl_llh.h"
#include "hw_atl2_utils.h" #include "hw_atl2_utils.h"
#include "hw_atl2_llh.h" #include "hw_atl2_llh.h"
...@@ -212,28 +213,6 @@ static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac) ...@@ -212,28 +213,6 @@ static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
hw_atl2_shared_buffer_get(self, mac_address, mac_address); hw_atl2_shared_buffer_get(self, mac_address, mac_address);
ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address); ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address);
if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
unsigned int rnd = 0;
u32 h;
u32 l;
get_random_bytes(&rnd, sizeof(unsigned int));
l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16);
h = 0x8001300EU;
mac[5] = (u8)(0xFFU & l);
l >>= 8;
mac[4] = (u8)(0xFFU & l);
l >>= 8;
mac[3] = (u8)(0xFFU & l);
l >>= 8;
mac[2] = (u8)(0xFFU & l);
mac[1] = (u8)(0xFFU & h);
h >>= 8;
mac[0] = (u8)(0xFFU & h);
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment