nfp: add support for eeprom get and set command
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>
This commit is contained in:
parent
2b88354d37
commit
e6686745e3
1 changed files with 157 additions and 0 deletions
|
|
@ -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 |
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue