@@ -254,6 +254,7 @@ static unsigned int nfp_pf_get_limit_vfs(struct nfp_pf *pf,
if (offset >= limit_vfs_rtsym)
return 0;
+ pf->multi_pf.vf_fid = offset;
if (offset + total > limit_vfs_rtsym)
return limit_vfs_rtsym - offset;
@@ -87,6 +87,7 @@ struct nfp_dumpspec {
* @multi_pf: Used in multi-PF setup
* @multi_pf.en: True if it's a NIC with multiple PFs
* @multi_pf.id: PF index
+ * @multi_pf.vf_fid: Id of first VF that belongs to this PF
* @multi_pf.beat_timer:Timer for beat to keepalive
* @multi_pf.beat_area: Pointer to CPP area for beat to keepalive
* @multi_pf.beat_addr: Pointer to mapped beat address used for keepalive
@@ -151,6 +152,7 @@ struct nfp_pf {
struct {
bool en;
u8 id;
+ u8 vf_fid;
struct timer_list beat_timer;
struct nfp_cpp_area *beat_area;
u8 __iomem *beat_addr;
@@ -293,6 +293,16 @@ static int nfp_net_pf_init_vnics(struct nfp_pf *pf)
return err;
}
+static void nfp_net_pf_clean_vnics(struct nfp_pf *pf)
+{
+ struct nfp_net *nn;
+
+ list_for_each_entry(nn, &pf->vnics, vnic_list) {
+ if (nfp_net_is_data_vnic(nn))
+ nfp_net_pf_clean_vnic(pf, nn);
+ }
+}
+
static int
nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)
{
@@ -852,11 +862,17 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
if (err)
goto err_stop_app;
+ err = nfp_net_pf_init_sriov(pf);
+ if (err)
+ goto err_clean_vnics;
+
devl_unlock(devlink);
devlink_register(devlink);
return 0;
+err_clean_vnics:
+ nfp_net_pf_clean_vnics(pf);
err_stop_app:
nfp_net_pf_app_stop(pf);
err_free_irqs:
@@ -14,6 +14,9 @@
#include "nfp_net.h"
#include "nfp_net_sriov.h"
+/* The configurations that precede VF creating. */
+#define NFP_NET_VF_PRE_CONFIG NFP_NET_VF_CFG_MB_CAP_SPLIT
+
static int
nfp_net_sriov_check(struct nfp_app *app, int vf, u16 cap, const char *msg, bool warn)
{
@@ -29,6 +32,10 @@ nfp_net_sriov_check(struct nfp_app *app, int vf, u16 cap, const char *msg, bool
return -EOPNOTSUPP;
}
+ /* No need to check vf for the pre-configurations. */
+ if (cap & NFP_NET_VF_PRE_CONFIG)
+ return 0;
+
if (vf < 0 || vf >= app->pf->num_vfs) {
if (warn)
nfp_warn(app->pf->cpp, "invalid VF id %d\n", vf);
@@ -309,3 +316,21 @@ int nfp_app_get_vf_config(struct net_device *netdev, int vf,
return 0;
}
+
+int nfp_net_pf_init_sriov(struct nfp_pf *pf)
+{
+ int err;
+
+ if (!pf->multi_pf.en || !pf->limit_vfs)
+ return 0;
+
+ err = nfp_net_sriov_check(pf->app, 0, NFP_NET_VF_CFG_MB_CAP_SPLIT, "split", true);
+ if (err)
+ return err;
+
+ writeb(pf->limit_vfs, pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_VF_CNT);
+
+ /* Reuse NFP_NET_VF_CFG_MB_VF_NUM to pass vf_fid to FW. */
+ return nfp_net_sriov_update(pf->app, pf->multi_pf.vf_fid,
+ NFP_NET_VF_CFG_MB_UPD_SPLIT, "split");
+}
@@ -21,6 +21,7 @@
#define NFP_NET_VF_CFG_MB_CAP_TRUST (0x1 << 4)
#define NFP_NET_VF_CFG_MB_CAP_VLAN_PROTO (0x1 << 5)
#define NFP_NET_VF_CFG_MB_CAP_RATE (0x1 << 6)
+#define NFP_NET_VF_CFG_MB_CAP_SPLIT (0x1 << 8)
#define NFP_NET_VF_CFG_MB_RET 0x2
#define NFP_NET_VF_CFG_MB_UPD 0x4
#define NFP_NET_VF_CFG_MB_UPD_MAC (0x1 << 0)
@@ -30,6 +31,8 @@
#define NFP_NET_VF_CFG_MB_UPD_TRUST (0x1 << 4)
#define NFP_NET_VF_CFG_MB_UPD_VLAN_PROTO (0x1 << 5)
#define NFP_NET_VF_CFG_MB_UPD_RATE (0x1 << 6)
+#define NFP_NET_VF_CFG_MB_UPD_SPLIT (0x1 << 8)
+#define NFP_NET_VF_CFG_MB_VF_CNT 0x6
#define NFP_NET_VF_CFG_MB_VF_NUM 0x7
/* VF config entry
@@ -68,4 +71,6 @@ int nfp_app_set_vf_link_state(struct net_device *netdev, int vf,
int nfp_app_get_vf_config(struct net_device *netdev, int vf,
struct ifla_vf_info *ivi);
+int nfp_net_pf_init_sriov(struct nfp_pf *pf);
+
#endif /* _NFP_NET_SRIOV_H_ */