Commit b33177f1 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'nfp-vf-rate-limit-support'

Simon Horman says:

====================
*nfp: VF rate limit support

this short series adds VF rate limiting to the NFP driver.

The first patch, as suggested by Jakub Kicinski, adds a helper
to check that ndo_set_vf_rate() rate parameters are sane.
It also provides a place for further parameter checking to live,
if needed in future.

The second patch adds VF rate limit support to the NFP driver.
It addresses several comments made on v1, including removing
the parameter check that is now provided by the helper added
in the first patch.
====================

Link: https://lore.kernel.org/r/20220511113932.92114-1-simon.horman@corigine.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 982c97ee e0d0e1fd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1903,6 +1903,7 @@ const struct net_device_ops nfp_nfd3_netdev_ops = {
	.ndo_vlan_rx_kill_vid	= nfp_net_vlan_rx_kill_vid,
	.ndo_set_vf_mac         = nfp_app_set_vf_mac,
	.ndo_set_vf_vlan        = nfp_app_set_vf_vlan,
	.ndo_set_vf_rate	= nfp_app_set_vf_rate,
	.ndo_set_vf_spoofchk    = nfp_app_set_vf_spoofchk,
	.ndo_set_vf_trust	= nfp_app_set_vf_trust,
	.ndo_get_vf_config	= nfp_app_get_vf_config,
+46 −2
Original line number Diff line number Diff line
@@ -142,6 +142,37 @@ int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
	return nfp_net_sriov_update(app, vf, update, "vlan");
}

int nfp_app_set_vf_rate(struct net_device *netdev, int vf,
			int min_tx_rate, int max_tx_rate)
{
	struct nfp_app *app = nfp_app_from_netdev(netdev);
	u32 vf_offset, ratevalue;
	int err;

	err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate");
	if (err)
		return err;

	if (max_tx_rate >= NFP_NET_VF_RATE_MAX ||
	    min_tx_rate >= NFP_NET_VF_RATE_MAX) {
		nfp_warn(app->cpp, "tx-rate exceeds %d.\n",
			 NFP_NET_VF_RATE_MAX);
		return -EINVAL;
	}

	vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
	ratevalue = FIELD_PREP(NFP_NET_VF_CFG_MAX_RATE,
			       max_tx_rate ? max_tx_rate :
			       NFP_NET_VF_RATE_MAX) |
		    FIELD_PREP(NFP_NET_VF_CFG_MIN_RATE, min_tx_rate);

	writel(ratevalue,
	       app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_RATE);

	return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_RATE,
				    "rate");
}

int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
{
	struct nfp_app *app = nfp_app_from_netdev(netdev);
@@ -228,9 +259,8 @@ int nfp_app_get_vf_config(struct net_device *netdev, int vf,
			  struct ifla_vf_info *ivi)
{
	struct nfp_app *app = nfp_app_from_netdev(netdev);
	unsigned int vf_offset;
	u32 vf_offset, mac_hi, rate;
	u32 vlan_tag;
	u32 mac_hi;
	u16 mac_lo;
	u8 flags;
	int err;
@@ -261,5 +291,19 @@ int nfp_app_get_vf_config(struct net_device *netdev, int vf,
	ivi->trusted = FIELD_GET(NFP_NET_VF_CFG_CTRL_TRUST, flags);
	ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags);

	err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_RATE, "rate");
	if (!err) {
		rate = readl(app->pf->vfcfg_tbl2 + vf_offset +
			     NFP_NET_VF_CFG_RATE);

		ivi->max_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MAX_RATE, rate);
		ivi->min_tx_rate = FIELD_GET(NFP_NET_VF_CFG_MIN_RATE, rate);

		if (ivi->max_tx_rate == NFP_NET_VF_RATE_MAX)
			ivi->max_tx_rate = 0;
		if (ivi->min_tx_rate == NFP_NET_VF_RATE_MAX)
			ivi->min_tx_rate = 0;
	}

	return 0;
}
+9 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#define   NFP_NET_VF_CFG_MB_CAP_LINK_STATE		  (0x1 << 3)
#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_RET				0x2
#define NFP_NET_VF_CFG_MB_UPD				0x4
#define   NFP_NET_VF_CFG_MB_UPD_MAC			  (0x1 << 0)
@@ -28,6 +29,7 @@
#define   NFP_NET_VF_CFG_MB_UPD_LINK_STATE		  (0x1 << 3)
#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_VF_NUM			0x7

/* VF config entry
@@ -48,10 +50,17 @@
#define   NFP_NET_VF_CFG_VLAN_PROT			  0xffff0000
#define   NFP_NET_VF_CFG_VLAN_QOS			  0xe000
#define   NFP_NET_VF_CFG_VLAN_VID			  0x0fff
#define NFP_NET_VF_CFG_RATE				0xc
#define   NFP_NET_VF_CFG_MIN_RATE			0x0000ffff
#define   NFP_NET_VF_CFG_MAX_RATE			0xffff0000

#define NFP_NET_VF_RATE_MAX			0xffff

int nfp_app_set_vf_mac(struct net_device *netdev, int vf, u8 *mac);
int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
			__be16 vlan_proto);
int nfp_app_set_vf_rate(struct net_device *netdev, int vf, int min_tx_rate,
			int max_tx_rate);
int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
int nfp_app_set_vf_trust(struct net_device *netdev, int vf, bool setting);
int nfp_app_set_vf_link_state(struct net_device *netdev, int vf,
+18 −10
Original line number Diff line number Diff line
@@ -2306,6 +2306,19 @@ static int rtnl_ensure_unique_netns(struct nlattr *tb[],
	return -EINVAL;
}

static	int rtnl_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
			     int max_tx_rate)
{
	const struct net_device_ops *ops = dev->netdev_ops;

	if (!ops->ndo_set_vf_rate)
		return -EOPNOTSUPP;
	if (max_tx_rate && max_tx_rate < min_tx_rate)
		return -EINVAL;

	return ops->ndo_set_vf_rate(dev, vf, min_tx_rate, max_tx_rate);
}

static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[],
			    struct netlink_ext_ack *extack)
{
@@ -2443,11 +2456,8 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
		if (err < 0)
			return err;

		err = -EOPNOTSUPP;
		if (ops->ndo_set_vf_rate)
			err = ops->ndo_set_vf_rate(dev, ivt->vf,
						   ivf.min_tx_rate,
						   ivt->rate);
		err = rtnl_set_vf_rate(dev, ivt->vf,
				       ivf.min_tx_rate, ivt->rate);
		if (err < 0)
			return err;
	}
@@ -2457,11 +2467,9 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)

		if (ivt->vf >= INT_MAX)
			return -EINVAL;
		err = -EOPNOTSUPP;
		if (ops->ndo_set_vf_rate)
			err = ops->ndo_set_vf_rate(dev, ivt->vf,
						   ivt->min_tx_rate,
						   ivt->max_tx_rate);

		err = rtnl_set_vf_rate(dev, ivt->vf,
				       ivt->min_tx_rate, ivt->max_tx_rate);
		if (err < 0)
			return err;
	}