Commit c9497c98 authored by Mohamad Haj Yahia's avatar Mohamad Haj Yahia Committed by Saeed Mahameed

net/mlx5: Add support for setting VF min rate

Add support for SRIOV VF min rate guarantee by using the TSAR BW share
weights mechanism.

The TSAR BW share vport attribute represents the weight of that vport
among the other vports weights which means that the actual vport BW
percentage is the same vport weight percentage among the total vports
weights sum.
Signed-off-by: default avatarMohamad Haj Yahia <mohamad@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 264d7bf3
...@@ -3021,11 +3021,8 @@ static int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate, ...@@ -3021,11 +3021,8 @@ static int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
if (min_tx_rate)
return -EOPNOTSUPP;
return mlx5_eswitch_set_vport_rate(mdev->priv.eswitch, vf + 1, return mlx5_eswitch_set_vport_rate(mdev->priv.eswitch, vf + 1,
max_tx_rate); max_tx_rate, min_tx_rate);
} }
static int mlx5_vport_link2ifla(u8 esw_link) static int mlx5_vport_link2ifla(u8 esw_link)
......
...@@ -1415,7 +1415,7 @@ static void esw_destroy_tsar(struct mlx5_eswitch *esw) ...@@ -1415,7 +1415,7 @@ static void esw_destroy_tsar(struct mlx5_eswitch *esw)
} }
static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num, static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num,
u32 initial_max_rate) u32 initial_max_rate, u32 initial_bw_share)
{ {
u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
struct mlx5_vport *vport = &esw->vports[vport_num]; struct mlx5_vport *vport = &esw->vports[vport_num];
...@@ -1439,6 +1439,7 @@ static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num, ...@@ -1439,6 +1439,7 @@ static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num,
esw->qos.root_tsar_id); esw->qos.root_tsar_id);
MLX5_SET(scheduling_context, &sched_ctx, max_average_bw, MLX5_SET(scheduling_context, &sched_ctx, max_average_bw,
initial_max_rate); initial_max_rate);
MLX5_SET(scheduling_context, &sched_ctx, bw_share, initial_bw_share);
err = mlx5_create_scheduling_element_cmd(dev, err = mlx5_create_scheduling_element_cmd(dev,
SCHEDULING_HIERARCHY_E_SWITCH, SCHEDULING_HIERARCHY_E_SWITCH,
...@@ -1473,7 +1474,7 @@ static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num) ...@@ -1473,7 +1474,7 @@ static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num)
} }
static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num, static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num,
u32 max_rate) u32 max_rate, u32 bw_share)
{ {
u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
struct mlx5_vport *vport = &esw->vports[vport_num]; struct mlx5_vport *vport = &esw->vports[vport_num];
...@@ -1497,7 +1498,9 @@ static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num, ...@@ -1497,7 +1498,9 @@ static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num,
esw->qos.root_tsar_id); esw->qos.root_tsar_id);
MLX5_SET(scheduling_context, &sched_ctx, max_average_bw, MLX5_SET(scheduling_context, &sched_ctx, max_average_bw,
max_rate); max_rate);
MLX5_SET(scheduling_context, &sched_ctx, bw_share, bw_share);
bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW; bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE;
err = mlx5_modify_scheduling_element_cmd(dev, err = mlx5_modify_scheduling_element_cmd(dev,
SCHEDULING_HIERARCHY_E_SWITCH, SCHEDULING_HIERARCHY_E_SWITCH,
...@@ -1563,7 +1566,8 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, ...@@ -1563,7 +1566,8 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
esw_apply_vport_conf(esw, vport); esw_apply_vport_conf(esw, vport);
/* Attach vport to the eswitch rate limiter */ /* Attach vport to the eswitch rate limiter */
if (esw_vport_enable_qos(esw, vport_num, vport->info.max_rate)) if (esw_vport_enable_qos(esw, vport_num, vport->info.max_rate,
vport->qos.bw_share))
esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num); esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num);
/* Sync with current vport context */ /* Sync with current vport context */
...@@ -1952,6 +1956,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, ...@@ -1952,6 +1956,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
ivi->qos = evport->info.qos; ivi->qos = evport->info.qos;
ivi->spoofchk = evport->info.spoofchk; ivi->spoofchk = evport->info.spoofchk;
ivi->trusted = evport->info.trusted; ivi->trusted = evport->info.trusted;
ivi->min_tx_rate = evport->info.min_rate;
ivi->max_tx_rate = evport->info.max_rate; ivi->max_tx_rate = evport->info.max_rate;
mutex_unlock(&esw->state_lock); mutex_unlock(&esw->state_lock);
...@@ -2046,23 +2051,103 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, ...@@ -2046,23 +2051,103 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
return 0; return 0;
} }
int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
int vport, u32 max_rate)
{ {
u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
struct mlx5_vport *evport; struct mlx5_vport *evport;
u32 max_guarantee = 0;
int i;
for (i = 0; i <= esw->total_vports; i++) {
evport = &esw->vports[i];
if (!evport->enabled || evport->info.min_rate < max_guarantee)
continue;
max_guarantee = evport->info.min_rate;
}
return max_t(u32, max_guarantee / fw_max_bw_share, 1);
}
static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
{
u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
struct mlx5_vport *evport;
u32 vport_max_rate;
u32 vport_min_rate;
u32 bw_share;
int err;
int i;
for (i = 0; i <= esw->total_vports; i++) {
evport = &esw->vports[i];
if (!evport->enabled)
continue;
vport_min_rate = evport->info.min_rate;
vport_max_rate = evport->info.max_rate;
bw_share = MLX5_MIN_BW_SHARE;
if (vport_min_rate)
bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate,
divider,
fw_max_bw_share);
if (bw_share == evport->qos.bw_share)
continue;
err = esw_vport_qos_config(esw, i, vport_max_rate,
bw_share);
if (!err)
evport->qos.bw_share = bw_share;
else
return err;
}
return 0;
}
int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,
u32 max_rate, u32 min_rate)
{
u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
bool min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) &&
fw_max_bw_share >= MLX5_MIN_BW_SHARE;
bool max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit);
struct mlx5_vport *evport;
u32 previous_min_rate;
u32 divider;
int err = 0; int err = 0;
if (!ESW_ALLOWED(esw)) if (!ESW_ALLOWED(esw))
return -EPERM; return -EPERM;
if (!LEGAL_VPORT(esw, vport)) if (!LEGAL_VPORT(esw, vport))
return -EINVAL; return -EINVAL;
if ((min_rate && !min_rate_supported) || (max_rate && !max_rate_supported))
return -EOPNOTSUPP;
mutex_lock(&esw->state_lock); mutex_lock(&esw->state_lock);
evport = &esw->vports[vport]; evport = &esw->vports[vport];
err = esw_vport_qos_config(esw, vport, max_rate);
if (min_rate == evport->info.min_rate)
goto set_max_rate;
previous_min_rate = evport->info.min_rate;
evport->info.min_rate = min_rate;
divider = calculate_vports_min_rate_divider(esw);
err = normalize_vports_min_rate(esw, divider);
if (err) {
evport->info.min_rate = previous_min_rate;
goto unlock;
}
set_max_rate:
if (max_rate == evport->info.max_rate)
goto unlock;
err = esw_vport_qos_config(esw, vport, max_rate, evport->qos.bw_share);
if (!err) if (!err)
evport->info.max_rate = max_rate; evport->info.max_rate = max_rate;
unlock:
mutex_unlock(&esw->state_lock); mutex_unlock(&esw->state_lock);
return err; return err;
} }
......
...@@ -50,6 +50,11 @@ ...@@ -50,6 +50,11 @@
#define FDB_UPLINK_VPORT 0xffff #define FDB_UPLINK_VPORT 0xffff
#define MLX5_MIN_BW_SHARE 1
#define MLX5_RATE_TO_BW_SHARE(rate, divider, limit) \
min_t(u32, max_t(u32, (rate) / (divider), MLX5_MIN_BW_SHARE), limit)
/* L2 -mac address based- hash helpers */ /* L2 -mac address based- hash helpers */
struct l2addr_node { struct l2addr_node {
struct hlist_node hlist; struct hlist_node hlist;
...@@ -116,6 +121,7 @@ struct mlx5_vport_info { ...@@ -116,6 +121,7 @@ struct mlx5_vport_info {
u8 qos; u8 qos;
u64 node_guid; u64 node_guid;
int link_state; int link_state;
u32 min_rate;
u32 max_rate; u32 max_rate;
bool spoofchk; bool spoofchk;
bool trusted; bool trusted;
...@@ -138,6 +144,7 @@ struct mlx5_vport { ...@@ -138,6 +144,7 @@ struct mlx5_vport {
struct { struct {
bool enabled; bool enabled;
u32 esw_tsar_ix; u32 esw_tsar_ix;
u32 bw_share;
} qos; } qos;
bool enabled; bool enabled;
...@@ -249,8 +256,8 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw, ...@@ -249,8 +256,8 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
int vport, bool spoofchk); int vport, bool spoofchk);
int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
int vport_num, bool setting); int vport_num, bool setting);
int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,
int vport, u32 max_rate); u32 max_rate, u32 min_rate);
int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
int vport, struct ifla_vf_info *ivi); int vport, struct ifla_vf_info *ivi);
int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
......
...@@ -547,7 +547,9 @@ struct mlx5_ifc_e_switch_cap_bits { ...@@ -547,7 +547,9 @@ struct mlx5_ifc_e_switch_cap_bits {
struct mlx5_ifc_qos_cap_bits { struct mlx5_ifc_qos_cap_bits {
u8 packet_pacing[0x1]; u8 packet_pacing[0x1];
u8 esw_scheduling[0x1]; u8 esw_scheduling[0x1];
u8 reserved_at_2[0x1e]; u8 esw_bw_share[0x1];
u8 esw_rate_limit[0x1];
u8 reserved_at_4[0x1c];
u8 reserved_at_20[0x20]; u8 reserved_at_20[0x20];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment