Skip to content

Commit

Permalink
nfp: add support for eeprom get and set command
Browse files Browse the repository at this point in the history
Add support for eeprom get and set operation with ethtool command.
with this change, we can support commands as:

 #ethtool -e enp101s0np0 offset 0 length 6
 Offset          Values
 ------          ------
 0x0000:         00 15 4d 16 66 33

 #ethtool -E enp101s0np0 magic 0x400019ee offset 5 length 1 value 0x88

We make this change to persist MAC change during driver reload and system
reboot.

Signed-off-by: Baowen Zheng <baowen.zheng@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Baowen Zheng authored and Paolo Abeni committed Aug 30, 2022
1 parent 2b88354 commit e668674
Showing 1 changed file with 157 additions and 0 deletions.
157 changes: 157 additions & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,160 @@ static int nfp_net_set_phys_id(struct net_device *netdev,
return err;
}

#define NFP_EEPROM_LEN ETH_ALEN

static int
nfp_net_get_eeprom_len(struct net_device *netdev)
{
struct nfp_eth_table_port *eth_port;
struct nfp_port *port;

port = nfp_port_from_netdev(netdev);
eth_port = __nfp_port_get_eth_port(port);
if (!eth_port)
return 0;

return NFP_EEPROM_LEN;
}

static int
nfp_net_get_nsp_hwindex(struct net_device *netdev,
struct nfp_nsp **nspptr,
u32 *index)
{
struct nfp_eth_table_port *eth_port;
struct nfp_port *port;
struct nfp_nsp *nsp;
int err;

port = nfp_port_from_netdev(netdev);
eth_port = __nfp_port_get_eth_port(port);
if (!eth_port)
return -EOPNOTSUPP;

nsp = nfp_nsp_open(port->app->cpp);
if (IS_ERR(nsp)) {
err = PTR_ERR(nsp);
netdev_err(netdev, "Failed to access the NSP: %d\n", err);
return err;
}

if (!nfp_nsp_has_hwinfo_lookup(nsp)) {
netdev_err(netdev, "NSP doesn't support PF MAC generation\n");
nfp_nsp_close(nsp);
return -EOPNOTSUPP;
}

*nspptr = nsp;
*index = eth_port->eth_index;

return 0;
}

static int
nfp_net_get_port_mac_by_hwinfo(struct net_device *netdev,
u8 *mac_addr)
{
char hwinfo[32] = {};
struct nfp_nsp *nsp;
u32 index;
int err;

err = nfp_net_get_nsp_hwindex(netdev, &nsp, &index);
if (err)
return err;

snprintf(hwinfo, sizeof(hwinfo), "eth%u.mac", index);
err = nfp_nsp_hwinfo_lookup(nsp, hwinfo, sizeof(hwinfo));
nfp_nsp_close(nsp);
if (err) {
netdev_err(netdev, "Reading persistent MAC address failed: %d\n",
err);
return -EOPNOTSUPP;
}

if (sscanf(hwinfo, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
&mac_addr[0], &mac_addr[1], &mac_addr[2],
&mac_addr[3], &mac_addr[4], &mac_addr[5]) != 6) {
netdev_err(netdev, "Can't parse persistent MAC address (%s)\n",
hwinfo);
return -EOPNOTSUPP;
}

return 0;
}

static int
nfp_net_set_port_mac_by_hwinfo(struct net_device *netdev,
u8 *mac_addr)
{
char hwinfo[32] = {};
struct nfp_nsp *nsp;
u32 index;
int err;

err = nfp_net_get_nsp_hwindex(netdev, &nsp, &index);
if (err)
return err;

snprintf(hwinfo, sizeof(hwinfo),
"eth%u.mac=%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
index, mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
mac_addr[4], mac_addr[5]);

err = nfp_nsp_hwinfo_set(nsp, hwinfo, sizeof(hwinfo));
nfp_nsp_close(nsp);
if (err) {
netdev_err(netdev, "HWinfo set failed: %d, hwinfo: %s\n",
err, hwinfo);
return -EOPNOTSUPP;
}

return 0;
}

static int
nfp_net_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct nfp_net *nn = netdev_priv(netdev);
u8 buf[NFP_EEPROM_LEN] = {};

if (eeprom->len == 0)
return -EINVAL;

if (nfp_net_get_port_mac_by_hwinfo(netdev, buf))
return -EOPNOTSUPP;

eeprom->magic = nn->pdev->vendor | (nn->pdev->device << 16);
memcpy(bytes, buf + eeprom->offset, eeprom->len);

return 0;
}

static int
nfp_net_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct nfp_net *nn = netdev_priv(netdev);
u8 buf[NFP_EEPROM_LEN] = {};

if (eeprom->len == 0)
return -EINVAL;

if (eeprom->magic != (nn->pdev->vendor | nn->pdev->device << 16))
return -EINVAL;

if (nfp_net_get_port_mac_by_hwinfo(netdev, buf))
return -EOPNOTSUPP;

memcpy(buf + eeprom->offset, bytes, eeprom->len);
if (nfp_net_set_port_mac_by_hwinfo(netdev, buf))
return -EOPNOTSUPP;

return 0;
}

static const struct ethtool_ops nfp_net_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
Expand All @@ -1687,6 +1841,9 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
.set_dump = nfp_app_set_dump,
.get_dump_flag = nfp_app_get_dump_flag,
.get_dump_data = nfp_app_get_dump_data,
.get_eeprom_len = nfp_net_get_eeprom_len,
.get_eeprom = nfp_net_get_eeprom,
.set_eeprom = nfp_net_set_eeprom,
.get_module_info = nfp_port_get_module_info,
.get_module_eeprom = nfp_port_get_module_eeprom,
.get_coalesce = nfp_net_get_coalesce,
Expand Down

0 comments on commit e668674

Please sign in to comment.