aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Shamay <idos@mellanox.com>2015-04-02 09:31:16 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-02 16:25:03 -0400
commitcda373f4849d5dd6fedceb4aeba35682a0e1a833 (patch)
tree5af89f4d32eaf487d59f27b711178025e49538f1
parent08068cd5683f11e4505aa9c8cc6ed5942f8ad299 (diff)
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 <idos@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c177
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c11
-rw-r--r--include/linux/mlx4/cmd.h2
3 files changed, 189 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 4c0c6c7e63e7..bc6e4c9b6bb5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -2781,6 +2781,103 @@ static int mlx4_slaves_closest_port(struct mlx4_dev *dev, int slave, int port)
2781 return port; 2781 return port;
2782} 2782}
2783 2783
2784static 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
2830static 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
2849static 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
2784int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac) 2881int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
2785{ 2882{
2786 struct mlx4_priv *priv = mlx4_priv(dev); 2883 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)
2824 port = mlx4_slaves_closest_port(dev, slave, port); 2921 port = mlx4_slaves_closest_port(dev, slave, port);
2825 vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; 2922 vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
2826 2923
2924 if (!mlx4_valid_vf_state_change(dev, port, vf_admin, vlan, qos))
2925 return -EPERM;
2926
2827 if ((0 == vlan) && (0 == qos)) 2927 if ((0 == vlan) && (0 == qos))
2828 vf_admin->default_vlan = MLX4_VGT; 2928 vf_admin->default_vlan = MLX4_VGT;
2829 else 2929 else
2830 vf_admin->default_vlan = vlan; 2930 vf_admin->default_vlan = vlan;
2831 vf_admin->default_qos = qos; 2931 vf_admin->default_qos = qos;
2832 2932
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
2833 if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port)) 2940 if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port))
2834 mlx4_info(dev, 2941 mlx4_info(dev,
2835 "updating vf %d port %d config will take effect on next VF restart\n", 2942 "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)
2838} 2945}
2839EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan); 2946EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);
2840 2947
2948int 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}
3009EXPORT_SYMBOL_GPL(mlx4_set_vf_rate);
3010
2841 /* mlx4_get_slave_default_vlan - 3011 /* mlx4_get_slave_default_vlan -
2842 * return true if VST ( default vlan) 3012 * return true if VST ( default vlan)
2843 * if VST, will return vlan & qos (if not NULL) 3013 * 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
2911 3081
2912 ivf->vlan = s_info->default_vlan; 3082 ivf->vlan = s_info->default_vlan;
2913 ivf->qos = s_info->default_qos; 3083 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
2915 ivf->min_tx_rate = 0; 3090 ivf->min_tx_rate = 0;
2916 ivf->spoofchk = s_info->spoofchk; 3091 ivf->spoofchk = s_info->spoofchk;
2917 ivf->linkstate = s_info->link_state; 3092 ivf->linkstate = s_info->link_state;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index d73ab1ba5a78..2a5df0aa2228 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2240,6 +2240,16 @@ static int mlx4_en_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos)
2240 return mlx4_set_vf_vlan(mdev->dev, en_priv->port, vf, vlan, qos); 2240 return mlx4_set_vf_vlan(mdev->dev, en_priv->port, vf, vlan, qos);
2241} 2241}
2242 2242
2243static 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
2243static int mlx4_en_set_vf_spoofchk(struct net_device *dev, int vf, bool setting) 2253static int mlx4_en_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
2244{ 2254{
2245 struct mlx4_en_priv *en_priv = netdev_priv(dev); 2255 struct mlx4_en_priv *en_priv = netdev_priv(dev);
@@ -2458,6 +2468,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
2458 .ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid, 2468 .ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid,
2459 .ndo_set_vf_mac = mlx4_en_set_vf_mac, 2469 .ndo_set_vf_mac = mlx4_en_set_vf_mac,
2460 .ndo_set_vf_vlan = mlx4_en_set_vf_vlan, 2470 .ndo_set_vf_vlan = mlx4_en_set_vf_vlan,
2471 .ndo_set_vf_rate = mlx4_en_set_vf_rate,
2461 .ndo_set_vf_spoofchk = mlx4_en_set_vf_spoofchk, 2472 .ndo_set_vf_spoofchk = mlx4_en_set_vf_spoofchk,
2462 .ndo_set_vf_link_state = mlx4_en_set_vf_link_state, 2473 .ndo_set_vf_link_state = mlx4_en_set_vf_link_state,
2463 .ndo_get_vf_config = mlx4_en_get_vf_config, 2474 .ndo_get_vf_config = mlx4_en_get_vf_config,
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 88326ed0033a..a788839f54bb 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -296,6 +296,8 @@ void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbo
296u32 mlx4_comm_get_version(void); 296u32 mlx4_comm_get_version(void);
297int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac); 297int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac);
298int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos); 298int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos);
299int mlx4_set_vf_rate(struct mlx4_dev *dev, int port, int vf, int min_tx_rate,
300 int max_tx_rate);
299int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting); 301int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting);
300int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf); 302int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf);
301int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state); 303int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state);