Commit d287532e authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'nfp-port-speed-and-eeprom-get-set-updates'

Simon Horman says:

====================
nfp: port speed and eeprom get/set updates

this short series is the initial updates for the NFP driver for the v6.1
Kernel. It covers two enhancements:

1. Patches 1/3 and 2/3:
   - Support cases where application firmware does not know port speeds
     a priori by relaying this information from the management firmware
     to the application firmware.

     This allows the existing mechanism, whereby the driver reports port
     speeds to user-space as provided by the application firmware, to work
     in this case.

2. Patch 2/3:
   - Add support for eeprom get and set command
====================

Link: https://lore.kernel.org/r/20220825141223.22346-1-simon.horman@corigine.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents f97e971d e6686745
...@@ -65,6 +65,7 @@ struct nfp_dumpspec { ...@@ -65,6 +65,7 @@ struct nfp_dumpspec {
* @num_vfs: Number of SR-IOV VFs enabled * @num_vfs: Number of SR-IOV VFs enabled
* @fw_loaded: Is the firmware loaded? * @fw_loaded: Is the firmware loaded?
* @unload_fw_on_remove:Do we need to unload firmware on driver removal? * @unload_fw_on_remove:Do we need to unload firmware on driver removal?
* @sp_indiff: Is the firmware indifferent to physical port speed?
* @ctrl_vnic: Pointer to the control vNIC if available * @ctrl_vnic: Pointer to the control vNIC if available
* @mip: MIP handle * @mip: MIP handle
* @rtbl: RTsym table * @rtbl: RTsym table
...@@ -114,6 +115,7 @@ struct nfp_pf { ...@@ -114,6 +115,7 @@ struct nfp_pf {
bool fw_loaded; bool fw_loaded;
bool unload_fw_on_remove; bool unload_fw_on_remove;
bool sp_indiff;
struct nfp_net *ctrl_vnic; struct nfp_net *ctrl_vnic;
...@@ -190,4 +192,7 @@ int nfp_shared_buf_pool_set(struct nfp_pf *pf, unsigned int sb, ...@@ -190,4 +192,7 @@ int nfp_shared_buf_pool_set(struct nfp_pf *pf, unsigned int sb,
int nfp_devlink_params_register(struct nfp_pf *pf); int nfp_devlink_params_register(struct nfp_pf *pf);
void nfp_devlink_params_unregister(struct nfp_pf *pf); void nfp_devlink_params_unregister(struct nfp_pf *pf);
unsigned int nfp_net_lr2speed(unsigned int linkrate);
unsigned int nfp_net_speed2lr(unsigned int speed);
#endif /* NFP_MAIN_H */ #endif /* NFP_MAIN_H */
...@@ -474,19 +474,22 @@ static void nfp_net_read_link_status(struct nfp_net *nn) ...@@ -474,19 +474,22 @@ static void nfp_net_read_link_status(struct nfp_net *nn)
{ {
unsigned long flags; unsigned long flags;
bool link_up; bool link_up;
u32 sts; u16 sts;
spin_lock_irqsave(&nn->link_status_lock, flags); spin_lock_irqsave(&nn->link_status_lock, flags);
sts = nn_readl(nn, NFP_NET_CFG_STS); sts = nn_readw(nn, NFP_NET_CFG_STS);
link_up = !!(sts & NFP_NET_CFG_STS_LINK); link_up = !!(sts & NFP_NET_CFG_STS_LINK);
if (nn->link_up == link_up) if (nn->link_up == link_up)
goto out; goto out;
nn->link_up = link_up; nn->link_up = link_up;
if (nn->port) if (nn->port) {
set_bit(NFP_PORT_CHANGED, &nn->port->flags); set_bit(NFP_PORT_CHANGED, &nn->port->flags);
if (nn->port->link_cb)
nn->port->link_cb(nn->port);
}
if (nn->link_up) { if (nn->link_up) {
netif_carrier_on(nn->dp.netdev); netif_carrier_on(nn->dp.netdev);
......
...@@ -148,6 +148,14 @@ int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem, ...@@ -148,6 +148,14 @@ int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
true)) true))
return -EINVAL; return -EINVAL;
break; break;
case NFP_NET_CFG_TLV_TYPE_SP_INDIFF:
if (length) {
dev_err(dev, "Unexpected len of SP_INDIFF TLV:%u\n", length);
return -EINVAL;
}
caps->sp_indiff = true;
break;
default: default:
if (!FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr)) if (!FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr))
break; break;
......
...@@ -193,6 +193,10 @@ ...@@ -193,6 +193,10 @@
#define NFP_NET_CFG_STS_LINK_RATE_40G 5 #define NFP_NET_CFG_STS_LINK_RATE_40G 5
#define NFP_NET_CFG_STS_LINK_RATE_50G 6 #define NFP_NET_CFG_STS_LINK_RATE_50G 6
#define NFP_NET_CFG_STS_LINK_RATE_100G 7 #define NFP_NET_CFG_STS_LINK_RATE_100G 7
/* NSP Link rate is a 16-bit word. It's determined by NSP and
* written to CFG BAR by NFP driver.
*/
#define NFP_NET_CFG_STS_NSP_LINK_RATE 0x0036
#define NFP_NET_CFG_CAP 0x0038 #define NFP_NET_CFG_CAP 0x0038
#define NFP_NET_CFG_MAX_TXRINGS 0x003c #define NFP_NET_CFG_MAX_TXRINGS 0x003c
#define NFP_NET_CFG_MAX_RXRINGS 0x0040 #define NFP_NET_CFG_MAX_RXRINGS 0x0040
...@@ -488,6 +492,10 @@ ...@@ -488,6 +492,10 @@
* %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN: * %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN:
* Same as %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS, but crypto TLS does stream scan * Same as %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS, but crypto TLS does stream scan
* RX sync, rather than kernel-assisted sync. * RX sync, rather than kernel-assisted sync.
*
* %NFP_NET_CFG_TLV_TYPE_SP_INDIFF:
* Empty, indicate the firmware is indifferent to port speed. Then no need to
* reload driver and firmware when port speed is changed.
*/ */
#define NFP_NET_CFG_TLV_TYPE_UNKNOWN 0 #define NFP_NET_CFG_TLV_TYPE_UNKNOWN 0
#define NFP_NET_CFG_TLV_TYPE_RESERVED 1 #define NFP_NET_CFG_TLV_TYPE_RESERVED 1
...@@ -501,6 +509,7 @@ ...@@ -501,6 +509,7 @@
#define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS 11 /* see crypto/fw.h */ #define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS 11 /* see crypto/fw.h */
#define NFP_NET_CFG_TLV_TYPE_VNIC_STATS 12 #define NFP_NET_CFG_TLV_TYPE_VNIC_STATS 12
#define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN 13 #define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN 13
#define NFP_NET_CFG_TLV_TYPE_SP_INDIFF 14
struct device; struct device;
...@@ -515,6 +524,7 @@ struct device; ...@@ -515,6 +524,7 @@ struct device;
* @vnic_stats_off: offset of vNIC stats area * @vnic_stats_off: offset of vNIC stats area
* @vnic_stats_cnt: number of vNIC stats * @vnic_stats_cnt: number of vNIC stats
* @tls_resync_ss: TLS resync will be performed via stream scan * @tls_resync_ss: TLS resync will be performed via stream scan
* @sp_indiff: Firmware is indifferent to port speed
*/ */
struct nfp_net_tlv_caps { struct nfp_net_tlv_caps {
u32 me_freq_mhz; u32 me_freq_mhz;
...@@ -527,6 +537,7 @@ struct nfp_net_tlv_caps { ...@@ -527,6 +537,7 @@ struct nfp_net_tlv_caps {
unsigned int vnic_stats_off; unsigned int vnic_stats_off;
unsigned int vnic_stats_cnt; unsigned int vnic_stats_cnt;
unsigned int tls_resync_ss:1; unsigned int tls_resync_ss:1;
unsigned int sp_indiff:1;
}; };
int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem, int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
......
...@@ -273,20 +273,11 @@ static int ...@@ -273,20 +273,11 @@ static int
nfp_net_get_link_ksettings(struct net_device *netdev, nfp_net_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd) struct ethtool_link_ksettings *cmd)
{ {
static const u32 ls_to_ethtool[] = {
[NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0,
[NFP_NET_CFG_STS_LINK_RATE_UNKNOWN] = SPEED_UNKNOWN,
[NFP_NET_CFG_STS_LINK_RATE_1G] = SPEED_1000,
[NFP_NET_CFG_STS_LINK_RATE_10G] = SPEED_10000,
[NFP_NET_CFG_STS_LINK_RATE_25G] = SPEED_25000,
[NFP_NET_CFG_STS_LINK_RATE_40G] = SPEED_40000,
[NFP_NET_CFG_STS_LINK_RATE_50G] = SPEED_50000,
[NFP_NET_CFG_STS_LINK_RATE_100G] = SPEED_100000,
};
struct nfp_eth_table_port *eth_port; struct nfp_eth_table_port *eth_port;
struct nfp_port *port; struct nfp_port *port;
struct nfp_net *nn; struct nfp_net *nn;
u32 sts, ls; unsigned int speed;
u16 sts;
/* Init to unknowns */ /* Init to unknowns */
ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
...@@ -319,18 +310,15 @@ nfp_net_get_link_ksettings(struct net_device *netdev, ...@@ -319,18 +310,15 @@ nfp_net_get_link_ksettings(struct net_device *netdev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
nn = netdev_priv(netdev); nn = netdev_priv(netdev);
sts = nn_readl(nn, NFP_NET_CFG_STS); sts = nn_readw(nn, NFP_NET_CFG_STS);
speed = nfp_net_lr2speed(FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts));
ls = FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts); if (!speed)
if (ls == NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (ls == NFP_NET_CFG_STS_LINK_RATE_UNKNOWN || if (speed != SPEED_UNKNOWN) {
ls >= ARRAY_SIZE(ls_to_ethtool)) cmd->base.speed = speed;
return 0; cmd->base.duplex = DUPLEX_FULL;
}
cmd->base.speed = ls_to_ethtool[ls];
cmd->base.duplex = DUPLEX_FULL;
return 0; return 0;
} }
...@@ -1676,6 +1664,160 @@ static int nfp_net_set_phys_id(struct net_device *netdev, ...@@ -1676,6 +1664,160 @@ static int nfp_net_set_phys_id(struct net_device *netdev,
return err; 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 = { static const struct ethtool_ops nfp_net_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS | .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES | ETHTOOL_COALESCE_MAX_FRAMES |
...@@ -1699,6 +1841,9 @@ static const struct ethtool_ops nfp_net_ethtool_ops = { ...@@ -1699,6 +1841,9 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
.set_dump = nfp_app_set_dump, .set_dump = nfp_app_set_dump,
.get_dump_flag = nfp_app_get_dump_flag, .get_dump_flag = nfp_app_get_dump_flag,
.get_dump_data = nfp_app_get_dump_data, .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_info = nfp_port_get_module_info,
.get_module_eeprom = nfp_port_get_module_eeprom, .get_module_eeprom = nfp_port_get_module_eeprom,
.get_coalesce = nfp_net_get_coalesce, .get_coalesce = nfp_net_get_coalesce,
......
...@@ -202,7 +202,11 @@ nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar, ...@@ -202,7 +202,11 @@ nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
goto err_free_prev; goto err_free_prev;
} }
if (nn->port)
nn->port->link_cb = nfp_net_refresh_port_table;
ctrl_bar += NFP_PF_CSR_SLICE_SIZE; ctrl_bar += NFP_PF_CSR_SLICE_SIZE;
pf->sp_indiff |= nn->tlv_caps.sp_indiff;
/* Kill the vNIC if app init marked it as invalid */ /* Kill the vNIC if app init marked it as invalid */
if (nn->port && nn->port->type == NFP_PORT_INVALID) if (nn->port && nn->port->type == NFP_PORT_INVALID)
...@@ -304,6 +308,37 @@ static int nfp_net_pf_init_vnics(struct nfp_pf *pf) ...@@ -304,6 +308,37 @@ static int nfp_net_pf_init_vnics(struct nfp_pf *pf)
return err; return err;
} }
static int nfp_net_pf_cfg_nsp(struct nfp_pf *pf, bool sp_indiff)
{
struct nfp_nsp *nsp;
char hwinfo[32];
int err;
nsp = nfp_nsp_open(pf->cpp);
if (IS_ERR(nsp)) {
err = PTR_ERR(nsp);
return err;
}
snprintf(hwinfo, sizeof(hwinfo), "sp_indiff=%d", sp_indiff);
err = nfp_nsp_hwinfo_set(nsp, hwinfo, sizeof(hwinfo));
if (err)
nfp_warn(pf->cpp, "HWinfo(sp_indiff=%d) set failed: %d\n", sp_indiff, err);
nfp_nsp_close(nsp);
return err;
}
static int nfp_net_pf_init_nsp(struct nfp_pf *pf)
{
return nfp_net_pf_cfg_nsp(pf, pf->sp_indiff);
}
static void nfp_net_pf_clean_nsp(struct nfp_pf *pf)
{
(void)nfp_net_pf_cfg_nsp(pf, false);
}
static int static int
nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride) nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)
{ {
...@@ -315,6 +350,8 @@ nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride) ...@@ -315,6 +350,8 @@ nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)
if (IS_ERR(pf->app)) if (IS_ERR(pf->app))
return PTR_ERR(pf->app); return PTR_ERR(pf->app);
pf->sp_indiff |= pf->app->type->id == NFP_APP_FLOWER_NIC;
devl_lock(devlink); devl_lock(devlink);
err = nfp_app_init(pf->app); err = nfp_app_init(pf->app);
devl_unlock(devlink); devl_unlock(devlink);
...@@ -523,6 +560,57 @@ static int nfp_net_pci_map_mem(struct nfp_pf *pf) ...@@ -523,6 +560,57 @@ static int nfp_net_pci_map_mem(struct nfp_pf *pf)
return err; return err;
} }
static const unsigned int lr_to_speed[] = {
[NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0,
[NFP_NET_CFG_STS_LINK_RATE_UNKNOWN] = SPEED_UNKNOWN,
[NFP_NET_CFG_STS_LINK_RATE_1G] = SPEED_1000,
[NFP_NET_CFG_STS_LINK_RATE_10G] = SPEED_10000,
[NFP_NET_CFG_STS_LINK_RATE_25G] = SPEED_25000,
[NFP_NET_CFG_STS_LINK_RATE_40G] = SPEED_40000,
[NFP_NET_CFG_STS_LINK_RATE_50G] = SPEED_50000,
[NFP_NET_CFG_STS_LINK_RATE_100G] = SPEED_100000,
};
unsigned int nfp_net_lr2speed(unsigned int linkrate)
{
if (linkrate < ARRAY_SIZE(lr_to_speed))
return lr_to_speed[linkrate];
return SPEED_UNKNOWN;
}
unsigned int nfp_net_speed2lr(unsigned int speed)
{
int i;
for (i = 0; i < ARRAY_SIZE(lr_to_speed); i++) {
if (speed == lr_to_speed[i])
return i;
}
return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN;
}
static void nfp_net_notify_port_speed(struct nfp_port *port)
{
struct net_device *netdev = port->netdev;
struct nfp_net *nn;
u16 sts;
if (!nfp_netdev_is_nfp_net(netdev))
return;
nn = netdev_priv(netdev);
sts = nn_readw(nn, NFP_NET_CFG_STS);
if (!(sts & NFP_NET_CFG_STS_LINK)) {
nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, NFP_NET_CFG_STS_LINK_RATE_UNKNOWN);
return;
}
nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, nfp_net_speed2lr(port->eth_port->speed));
}
static int static int
nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port, nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
struct nfp_eth_table *eth_table) struct nfp_eth_table *eth_table)
...@@ -544,6 +632,7 @@ nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port, ...@@ -544,6 +632,7 @@ nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
} }
memcpy(port->eth_port, eth_port, sizeof(*eth_port)); memcpy(port->eth_port, eth_port, sizeof(*eth_port));
nfp_net_notify_port_speed(port);
return 0; return 0;
} }
...@@ -725,10 +814,14 @@ int nfp_net_pci_probe(struct nfp_pf *pf) ...@@ -725,10 +814,14 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
if (err) if (err)
goto err_clean_ddir; goto err_clean_ddir;
err = nfp_net_pf_alloc_irqs(pf); err = nfp_net_pf_init_nsp(pf);
if (err) if (err)
goto err_free_vnics; goto err_free_vnics;
err = nfp_net_pf_alloc_irqs(pf);
if (err)
goto err_clean_nsp;
err = nfp_net_pf_app_start(pf); err = nfp_net_pf_app_start(pf);
if (err) if (err)
goto err_free_irqs; goto err_free_irqs;
...@@ -746,6 +839,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf) ...@@ -746,6 +839,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
nfp_net_pf_app_stop(pf); nfp_net_pf_app_stop(pf);
err_free_irqs: err_free_irqs:
nfp_net_pf_free_irqs(pf); nfp_net_pf_free_irqs(pf);
err_clean_nsp:
nfp_net_pf_clean_nsp(pf);
err_free_vnics: err_free_vnics:
nfp_net_pf_free_vnics(pf); nfp_net_pf_free_vnics(pf);
err_clean_ddir: err_clean_ddir:
...@@ -776,6 +871,7 @@ void nfp_net_pci_remove(struct nfp_pf *pf) ...@@ -776,6 +871,7 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
nfp_net_pf_free_vnic(pf, nn); nfp_net_pf_free_vnic(pf, nn);
} }
nfp_net_pf_clean_nsp(pf);
nfp_net_pf_app_stop(pf); nfp_net_pf_app_stop(pf);
/* stop app first, to avoid double free of ctrl vNIC's ddir */ /* stop app first, to avoid double free of ctrl vNIC's ddir */
nfp_net_debugfs_dir_clean(&pf->ddir); nfp_net_debugfs_dir_clean(&pf->ddir);
......
...@@ -46,6 +46,7 @@ enum nfp_port_flags { ...@@ -46,6 +46,7 @@ enum nfp_port_flags {
* @tc_offload_cnt: number of active TC offloads, how offloads are counted * @tc_offload_cnt: number of active TC offloads, how offloads are counted
* is not defined, use as a boolean * is not defined, use as a boolean
* @app: backpointer to the app structure * @app: backpointer to the app structure
* @link_cb: callback when link status changed
* @dl_port: devlink port structure * @dl_port: devlink port structure
* @eth_id: for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme * @eth_id: for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme
* @eth_forced: for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change * @eth_forced: for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change
...@@ -66,6 +67,7 @@ struct nfp_port { ...@@ -66,6 +67,7 @@ struct nfp_port {
unsigned long tc_offload_cnt; unsigned long tc_offload_cnt;
struct nfp_app *app; struct nfp_app *app;
void (*link_cb)(struct nfp_port *port);
struct devlink_port dl_port; struct devlink_port dl_port;
......
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