Skip to content

Commit cda373f

Browse files
shamoyadavem330
authored andcommitted
net/mlx4_en: Enable TX rate limit per VF
Support granular QoS per VF, by implementing the ndo_set_vf_rate. Enforce a rate limit per VF when called, and enabled only for VFs in VST mode with user priority supported by the device. We don't enforce VFs to be in VST mode at the moment of configuration, but rather save the given rate limit and enforce it when the VF is moved to VST with user priority which is supported (currently 0). VST<->VGT or VST qos value state changes are disallowed when a rate limit is configured. Minimum BW share is not supported yet. Signed-off-by: Ido Shamay <[email protected]> Signed-off-by: Or Gerlitz <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 08068cd commit cda373f

File tree

3 files changed

+189
-1
lines changed

3 files changed

+189
-1
lines changed

drivers/net/ethernet/mellanox/mlx4/cmd.c

Lines changed: 176 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2781,6 +2781,103 @@ static int mlx4_slaves_closest_port(struct mlx4_dev *dev, int slave, int port)
27812781
return port;
27822782
}
27832783

2784+
static int mlx4_set_vport_qos(struct mlx4_priv *priv, int slave, int port,
2785+
int max_tx_rate)
2786+
{
2787+
int i;
2788+
int err;
2789+
struct mlx4_qos_manager *port_qos;
2790+
struct mlx4_dev *dev = &priv->dev;
2791+
struct mlx4_vport_qos_param vpp_qos[MLX4_NUM_UP];
2792+
2793+
port_qos = &priv->mfunc.master.qos_ctl[port];
2794+
memset(vpp_qos, 0, sizeof(struct mlx4_vport_qos_param) * MLX4_NUM_UP);
2795+
2796+
if (slave > port_qos->num_of_qos_vfs) {
2797+
mlx4_info(dev, "No availible VPP resources for this VF\n");
2798+
return -EINVAL;
2799+
}
2800+
2801+
/* Query for default QoS values from Vport 0 is needed */
2802+
err = mlx4_SET_VPORT_QOS_get(dev, port, 0, vpp_qos);
2803+
if (err) {
2804+
mlx4_info(dev, "Failed to query Vport 0 QoS values\n");
2805+
return err;
2806+
}
2807+
2808+
for (i = 0; i < MLX4_NUM_UP; i++) {
2809+
if (test_bit(i, port_qos->priority_bm) && max_tx_rate) {
2810+
vpp_qos[i].max_avg_bw = max_tx_rate;
2811+
vpp_qos[i].enable = 1;
2812+
} else {
2813+
/* if user supplied tx_rate == 0, meaning no rate limit
2814+
* configuration is required. so we are leaving the
2815+
* value of max_avg_bw as queried from Vport 0.
2816+
*/
2817+
vpp_qos[i].enable = 0;
2818+
}
2819+
}
2820+
2821+
err = mlx4_SET_VPORT_QOS_set(dev, port, slave, vpp_qos);
2822+
if (err) {
2823+
mlx4_info(dev, "Failed to set Vport %d QoS values\n", slave);
2824+
return err;
2825+
}
2826+
2827+
return 0;
2828+
}
2829+
2830+
static bool mlx4_is_vf_vst_and_prio_qos(struct mlx4_dev *dev, int port,
2831+
struct mlx4_vport_state *vf_admin)
2832+
{
2833+
struct mlx4_qos_manager *info;
2834+
struct mlx4_priv *priv = mlx4_priv(dev);
2835+
2836+
if (!mlx4_is_master(dev) ||
2837+
!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QOS_VPP))
2838+
return false;
2839+
2840+
info = &priv->mfunc.master.qos_ctl[port];
2841+
2842+
if (vf_admin->default_vlan != MLX4_VGT &&
2843+
test_bit(vf_admin->default_qos, info->priority_bm))
2844+
return true;
2845+
2846+
return false;
2847+
}
2848+
2849+
static bool mlx4_valid_vf_state_change(struct mlx4_dev *dev, int port,
2850+
struct mlx4_vport_state *vf_admin,
2851+
int vlan, int qos)
2852+
{
2853+
struct mlx4_vport_state dummy_admin = {0};
2854+
2855+
if (!mlx4_is_vf_vst_and_prio_qos(dev, port, vf_admin) ||
2856+
!vf_admin->tx_rate)
2857+
return true;
2858+
2859+
dummy_admin.default_qos = qos;
2860+
dummy_admin.default_vlan = vlan;
2861+
2862+
/* VF wants to move to other VST state which is valid with current
2863+
* rate limit. Either differnt default vlan in VST or other
2864+
* supported QoS priority. Otherwise we don't allow this change when
2865+
* the TX rate is still configured.
2866+
*/
2867+
if (mlx4_is_vf_vst_and_prio_qos(dev, port, &dummy_admin))
2868+
return true;
2869+
2870+
mlx4_info(dev, "Cannot change VF state to %s while rate is set\n",
2871+
(vlan == MLX4_VGT) ? "VGT" : "VST");
2872+
2873+
if (vlan != MLX4_VGT)
2874+
mlx4_info(dev, "VST priority %d not supported for QoS\n", qos);
2875+
2876+
mlx4_info(dev, "Please set rate to 0 prior to this VF state change\n");
2877+
2878+
return false;
2879+
}
2880+
27842881
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
27852882
{
27862883
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -2824,12 +2921,22 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
28242921
port = mlx4_slaves_closest_port(dev, slave, port);
28252922
vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
28262923

2924+
if (!mlx4_valid_vf_state_change(dev, port, vf_admin, vlan, qos))
2925+
return -EPERM;
2926+
28272927
if ((0 == vlan) && (0 == qos))
28282928
vf_admin->default_vlan = MLX4_VGT;
28292929
else
28302930
vf_admin->default_vlan = vlan;
28312931
vf_admin->default_qos = qos;
28322932

2933+
/* If rate was configured prior to VST, we saved the configured rate
2934+
* in vf_admin->rate and now, if priority supported we enforce the QoS
2935+
*/
2936+
if (mlx4_is_vf_vst_and_prio_qos(dev, port, vf_admin) &&
2937+
vf_admin->tx_rate)
2938+
vf_admin->qos_vport = slave;
2939+
28332940
if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port))
28342941
mlx4_info(dev,
28352942
"updating vf %d port %d config will take effect on next VF restart\n",
@@ -2838,6 +2945,69 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
28382945
}
28392946
EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);
28402947

2948+
int mlx4_set_vf_rate(struct mlx4_dev *dev, int port, int vf, int min_tx_rate,
2949+
int max_tx_rate)
2950+
{
2951+
int err;
2952+
int slave;
2953+
struct mlx4_vport_state *vf_admin;
2954+
struct mlx4_priv *priv = mlx4_priv(dev);
2955+
2956+
if (!mlx4_is_master(dev) ||
2957+
!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QOS_VPP))
2958+
return -EPROTONOSUPPORT;
2959+
2960+
if (min_tx_rate) {
2961+
mlx4_info(dev, "Minimum BW share not supported\n");
2962+
return -EPROTONOSUPPORT;
2963+
}
2964+
2965+
slave = mlx4_get_slave_indx(dev, vf);
2966+
if (slave < 0)
2967+
return -EINVAL;
2968+
2969+
port = mlx4_slaves_closest_port(dev, slave, port);
2970+
vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
2971+
2972+
err = mlx4_set_vport_qos(priv, slave, port, max_tx_rate);
2973+
if (err) {
2974+
mlx4_info(dev, "vf %d failed to set rate %d\n", vf,
2975+
max_tx_rate);
2976+
return err;
2977+
}
2978+
2979+
vf_admin->tx_rate = max_tx_rate;
2980+
/* if VF is not in supported mode (VST with supported prio),
2981+
* we do not change vport configuration for its QPs, but save
2982+
* the rate, so it will be enforced when it moves to supported
2983+
* mode next time.
2984+
*/
2985+
if (!mlx4_is_vf_vst_and_prio_qos(dev, port, vf_admin)) {
2986+
mlx4_info(dev,
2987+
"rate set for VF %d when not in valid state\n", vf);
2988+
2989+
if (vf_admin->default_vlan != MLX4_VGT)
2990+
mlx4_info(dev, "VST priority not supported by QoS\n");
2991+
else
2992+
mlx4_info(dev, "VF in VGT mode (needed VST)\n");
2993+
2994+
mlx4_info(dev,
2995+
"rate %d take affect when VF moves to valid state\n",
2996+
max_tx_rate);
2997+
return 0;
2998+
}
2999+
3000+
/* If user sets rate 0 assigning default vport for its QPs */
3001+
vf_admin->qos_vport = max_tx_rate ? slave : MLX4_VPP_DEFAULT_VPORT;
3002+
3003+
if (priv->mfunc.master.slave_state[slave].active &&
3004+
dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP)
3005+
mlx4_master_immediate_activate_vlan_qos(priv, slave, port);
3006+
3007+
return 0;
3008+
}
3009+
EXPORT_SYMBOL_GPL(mlx4_set_vf_rate);
3010+
28413011
/* mlx4_get_slave_default_vlan -
28423012
* return true if VST ( default vlan)
28433013
* if VST, will return vlan & qos (if not NULL)
@@ -2911,7 +3081,12 @@ int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_in
29113081

29123082
ivf->vlan = s_info->default_vlan;
29133083
ivf->qos = s_info->default_qos;
2914-
ivf->max_tx_rate = s_info->tx_rate;
3084+
3085+
if (mlx4_is_vf_vst_and_prio_qos(dev, port, s_info))
3086+
ivf->max_tx_rate = s_info->tx_rate;
3087+
else
3088+
ivf->max_tx_rate = 0;
3089+
29153090
ivf->min_tx_rate = 0;
29163091
ivf->spoofchk = s_info->spoofchk;
29173092
ivf->linkstate = s_info->link_state;

drivers/net/ethernet/mellanox/mlx4/en_netdev.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,6 +2240,16 @@ static int mlx4_en_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos)
22402240
return mlx4_set_vf_vlan(mdev->dev, en_priv->port, vf, vlan, qos);
22412241
}
22422242

2243+
static int mlx4_en_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
2244+
int max_tx_rate)
2245+
{
2246+
struct mlx4_en_priv *en_priv = netdev_priv(dev);
2247+
struct mlx4_en_dev *mdev = en_priv->mdev;
2248+
2249+
return mlx4_set_vf_rate(mdev->dev, en_priv->port, vf, min_tx_rate,
2250+
max_tx_rate);
2251+
}
2252+
22432253
static int mlx4_en_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
22442254
{
22452255
struct mlx4_en_priv *en_priv = netdev_priv(dev);
@@ -2458,6 +2468,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
24582468
.ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid,
24592469
.ndo_set_vf_mac = mlx4_en_set_vf_mac,
24602470
.ndo_set_vf_vlan = mlx4_en_set_vf_vlan,
2471+
.ndo_set_vf_rate = mlx4_en_set_vf_rate,
24612472
.ndo_set_vf_spoofchk = mlx4_en_set_vf_spoofchk,
24622473
.ndo_set_vf_link_state = mlx4_en_set_vf_link_state,
24632474
.ndo_get_vf_config = mlx4_en_get_vf_config,

include/linux/mlx4/cmd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbo
296296
u32 mlx4_comm_get_version(void);
297297
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac);
298298
int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos);
299+
int mlx4_set_vf_rate(struct mlx4_dev *dev, int port, int vf, int min_tx_rate,
300+
int max_tx_rate);
299301
int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting);
300302
int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf);
301303
int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state);

0 commit comments

Comments
 (0)