aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_main.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c8
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h7
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_main.c43
4 files changed, 59 insertions, 1 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h
index be3746cbc58b..6805af186f1b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h
@@ -65,6 +65,7 @@ struct nfp_dumpspec {
* @num_vfs: Number of SR-IOV VFs enabled
* @fw_loaded: Is the firmware loaded?
* @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
* @mip: MIP handle
* @rtbl: RTsym table
@@ -114,6 +115,7 @@ struct nfp_pf {
bool fw_loaded;
bool unload_fw_on_remove;
+ bool sp_indiff;
struct nfp_net *ctrl_vnic;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c
index c3a763134e79..d81bd8697047 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c
@@ -148,6 +148,14 @@ int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
true))
return -EINVAL;
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:
if (!FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr))
break;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
index 91708527a47c..1d53f721a1c8 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
@@ -492,6 +492,10 @@
* %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN:
* Same as %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS, but crypto TLS does stream scan
* 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_RESERVED 1
@@ -505,6 +509,7 @@
#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_CRYPTO_OPS_RX_SCAN 13
+#define NFP_NET_CFG_TLV_TYPE_SP_INDIFF 14
struct device;
@@ -519,6 +524,7 @@ struct device;
* @vnic_stats_off: offset of vNIC stats area
* @vnic_stats_cnt: number of vNIC stats
* @tls_resync_ss: TLS resync will be performed via stream scan
+ * @sp_indiff: Firmware is indifferent to port speed
*/
struct nfp_net_tlv_caps {
u32 me_freq_mhz;
@@ -531,6 +537,7 @@ struct nfp_net_tlv_caps {
unsigned int vnic_stats_off;
unsigned int vnic_stats_cnt;
unsigned int tls_resync_ss:1;
+ unsigned int sp_indiff:1;
};
int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index dd668520851e..e2d4c487e8de 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -206,6 +206,7 @@ nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
nn->port->link_cb = nfp_net_refresh_port_table;
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 */
if (nn->port && nn->port->type == NFP_PORT_INVALID)
@@ -307,6 +308,37 @@ err_prev_deinit:
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
nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)
{
@@ -318,6 +350,8 @@ nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)
if (IS_ERR(pf->app))
return PTR_ERR(pf->app);
+ pf->sp_indiff |= pf->app->type->id == NFP_APP_FLOWER_NIC;
+
devl_lock(devlink);
err = nfp_app_init(pf->app);
devl_unlock(devlink);
@@ -780,10 +814,14 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
if (err)
goto err_clean_ddir;
- err = nfp_net_pf_alloc_irqs(pf);
+ err = nfp_net_pf_init_nsp(pf);
if (err)
goto err_free_vnics;
+ err = nfp_net_pf_alloc_irqs(pf);
+ if (err)
+ goto err_clean_nsp;
+
err = nfp_net_pf_app_start(pf);
if (err)
goto err_free_irqs;
@@ -801,6 +839,8 @@ err_stop_app:
nfp_net_pf_app_stop(pf);
err_free_irqs:
nfp_net_pf_free_irqs(pf);
+err_clean_nsp:
+ nfp_net_pf_clean_nsp(pf);
err_free_vnics:
nfp_net_pf_free_vnics(pf);
err_clean_ddir:
@@ -831,6 +871,7 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
nfp_net_pf_free_vnic(pf, nn);
}
+ nfp_net_pf_clean_nsp(pf);
nfp_net_pf_app_stop(pf);
/* stop app first, to avoid double free of ctrl vNIC's ddir */
nfp_net_debugfs_dir_clean(&pf->ddir);