diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h index be3746cbc58be3e2e27ddea2c2d5d7c5c3bc3c38..6805af186f1ba19824244eb0f8c1ab0ac0fcd5a1 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 c3a763134e79fe5f96fc42b8a0a0c2711c111cbf..d81bd86970471b3ec5aaf4c1caa485ace27275c9 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 91708527a47c6a659604c6c387fab4c1964757c1..1d53f721a1c82f9fd574e62e9c632e3b414e1989 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 dd668520851ed1c6559a97a40fc6abcf90cdefa8..e2d4c487e8de9a0a3f6802a9b70ca29463855dc6 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 @@ static int nfp_net_pf_init_vnics(struct nfp_pf *pf) 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 @@ int nfp_net_pci_probe(struct nfp_pf *pf) 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);