Commit 45f171b1 authored by Maxim Mikityanskiy's avatar Maxim Mikityanskiy Committed by Saeed Mahameed

net/mlx5e: Support LAG TX port affinity distribution

When the VF LAG is in use, round-robin the TX affinity of channels among
the different ports, if supported by the firmware. Create a set of TISes
per port, while doing round-robin of the channels over the different
sets. Let all SQs of a channel share the same set of TISes.

If lag_tx_port_affinity HCA cap bit is supported, num_lag_ports > 1 and
we aren't the LACP owner (PF in the regular use), assign the affinities,
otherwise use tx_affinity == 0 in TIS context to let the FW assign the
affinities itself. The TISes of the LACP owner are mapped only to the
native physical port.

For VFs, the starting port for round-robin is determined by its vhca_id,
because a VF may have only one channel if attached to a single-core VM.
Signed-off-by: default avatarMaxim Mikityanskiy <maximmi@mellanox.com>
Signed-off-by: default avatarTariq Toukan <tariqt@mellanox.com>
Signed-off-by: default avatarMark Bloch <markb@mellanox.com>
Reviewed-by: default avatarTariq Toukan <tariqt@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 3c145626
...@@ -163,6 +163,14 @@ enum mlx5e_rq_group { ...@@ -163,6 +163,14 @@ enum mlx5e_rq_group {
#define MLX5E_NUM_RQ_GROUPS(g) (1 + MLX5E_RQ_GROUP_##g) #define MLX5E_NUM_RQ_GROUPS(g) (1 + MLX5E_RQ_GROUP_##g)
}; };
static inline u8 mlx5e_get_num_lag_ports(struct mlx5_core_dev *mdev)
{
if (mlx5_lag_is_lacp_owner(mdev))
return 1;
return clamp_t(u8, MLX5_CAP_GEN(mdev, num_lag_ports), 1, MLX5_MAX_PORTS);
}
static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size) static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size)
{ {
switch (wq_type) { switch (wq_type) {
...@@ -705,6 +713,7 @@ struct mlx5e_channel { ...@@ -705,6 +713,7 @@ struct mlx5e_channel {
struct net_device *netdev; struct net_device *netdev;
__be32 mkey_be; __be32 mkey_be;
u8 num_tc; u8 num_tc;
u8 lag_port;
/* XDP_REDIRECT */ /* XDP_REDIRECT */
struct mlx5e_xdpsq xdpsq; struct mlx5e_xdpsq xdpsq;
...@@ -818,7 +827,7 @@ struct mlx5e_priv { ...@@ -818,7 +827,7 @@ struct mlx5e_priv {
struct mlx5e_rq drop_rq; struct mlx5e_rq drop_rq;
struct mlx5e_channels channels; struct mlx5e_channels channels;
u32 tisn[MLX5E_MAX_NUM_TC]; u32 tisn[MLX5_MAX_PORTS][MLX5E_MAX_NUM_TC];
struct mlx5e_rqt indir_rqt; struct mlx5e_rqt indir_rqt;
struct mlx5e_tir indir_tir[MLX5E_NUM_INDIR_TIRS]; struct mlx5e_tir indir_tir[MLX5E_NUM_INDIR_TIRS];
struct mlx5e_tir inner_indir_tir[MLX5E_NUM_INDIR_TIRS]; struct mlx5e_tir inner_indir_tir[MLX5E_NUM_INDIR_TIRS];
......
...@@ -1442,7 +1442,7 @@ int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params, ...@@ -1442,7 +1442,7 @@ int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params,
return err; return err;
csp.tis_lst_sz = 1; csp.tis_lst_sz = 1;
csp.tisn = c->priv->tisn[0]; /* tc = 0 */ csp.tisn = c->priv->tisn[c->lag_port][0]; /* tc = 0 */
csp.cqn = sq->cq.mcq.cqn; csp.cqn = sq->cq.mcq.cqn;
csp.wq_ctrl = &sq->wq_ctrl; csp.wq_ctrl = &sq->wq_ctrl;
csp.min_inline_mode = sq->min_inline_mode; csp.min_inline_mode = sq->min_inline_mode;
...@@ -1692,7 +1692,7 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c, ...@@ -1692,7 +1692,7 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c,
for (tc = 0; tc < params->num_tc; tc++) { for (tc = 0; tc < params->num_tc; tc++) {
int txq_ix = c->ix + tc * priv->max_nch; int txq_ix = c->ix + tc * priv->max_nch;
err = mlx5e_open_txqsq(c, c->priv->tisn[tc], txq_ix, err = mlx5e_open_txqsq(c, c->priv->tisn[c->lag_port][tc], txq_ix,
params, &cparam->sq, &c->sq[tc], tc); params, &cparam->sq, &c->sq[tc], tc);
if (err) if (err)
goto err_close_sqs; goto err_close_sqs;
...@@ -1926,6 +1926,13 @@ static void mlx5e_close_queues(struct mlx5e_channel *c) ...@@ -1926,6 +1926,13 @@ static void mlx5e_close_queues(struct mlx5e_channel *c)
mlx5e_close_cq(&c->icosq.cq); mlx5e_close_cq(&c->icosq.cq);
} }
static u8 mlx5e_enumerate_lag_port(struct mlx5_core_dev *mdev, int ix)
{
u16 port_aff_bias = mlx5_core_is_pf(mdev) ? 0 : MLX5_CAP_GEN(mdev, vhca_id);
return (ix + port_aff_bias) % mlx5e_get_num_lag_ports(mdev);
}
static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
struct mlx5e_params *params, struct mlx5e_params *params,
struct mlx5e_channel_param *cparam, struct mlx5e_channel_param *cparam,
...@@ -1960,6 +1967,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, ...@@ -1960,6 +1967,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
c->xdp = !!params->xdp_prog; c->xdp = !!params->xdp_prog;
c->stats = &priv->channel_stats[ix].ch; c->stats = &priv->channel_stats[ix].ch;
c->irq_desc = irq_to_desc(irq); c->irq_desc = irq_to_desc(irq);
c->lag_port = mlx5e_enumerate_lag_port(priv->mdev, ix);
err = mlx5e_alloc_xps_cpumask(c, params); err = mlx5e_alloc_xps_cpumask(c, params);
if (err) if (err)
...@@ -3181,35 +3189,49 @@ void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn) ...@@ -3181,35 +3189,49 @@ void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn)
void mlx5e_destroy_tises(struct mlx5e_priv *priv) void mlx5e_destroy_tises(struct mlx5e_priv *priv)
{ {
int tc; int tc, i;
for (tc = 0; tc < priv->profile->max_tc; tc++) for (i = 0; i < mlx5e_get_num_lag_ports(priv->mdev); i++)
mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]); for (tc = 0; tc < priv->profile->max_tc; tc++)
mlx5e_destroy_tis(priv->mdev, priv->tisn[i][tc]);
}
static bool mlx5e_lag_should_assign_affinity(struct mlx5_core_dev *mdev)
{
return MLX5_CAP_GEN(mdev, lag_tx_port_affinity) && mlx5e_get_num_lag_ports(mdev) > 1;
} }
int mlx5e_create_tises(struct mlx5e_priv *priv) int mlx5e_create_tises(struct mlx5e_priv *priv)
{ {
int tc, i;
int err; int err;
int tc;
for (tc = 0; tc < priv->profile->max_tc; tc++) { for (i = 0; i < mlx5e_get_num_lag_ports(priv->mdev); i++) {
u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {}; for (tc = 0; tc < priv->profile->max_tc; tc++) {
void *tisc; u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {};
void *tisc;
tisc = MLX5_ADDR_OF(create_tis_in, in, ctx); tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
MLX5_SET(tisc, tisc, prio, tc << 1); MLX5_SET(tisc, tisc, prio, tc << 1);
err = mlx5e_create_tis(priv->mdev, in, &priv->tisn[tc]); if (mlx5e_lag_should_assign_affinity(priv->mdev))
if (err) MLX5_SET(tisc, tisc, lag_tx_port_affinity, i + 1);
goto err_close_tises;
err = mlx5e_create_tis(priv->mdev, in, &priv->tisn[i][tc]);
if (err)
goto err_close_tises;
}
} }
return 0; return 0;
err_close_tises: err_close_tises:
for (tc--; tc >= 0; tc--) for (; i >= 0; i--) {
mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]); for (tc--; tc >= 0; tc--)
mlx5e_destroy_tis(priv->mdev, priv->tisn[i][tc]);
tc = priv->profile->max_tc;
}
return err; return err;
} }
......
...@@ -279,7 +279,7 @@ static int mlx5i_init_tx(struct mlx5e_priv *priv) ...@@ -279,7 +279,7 @@ static int mlx5i_init_tx(struct mlx5e_priv *priv)
return err; return err;
} }
err = mlx5i_create_tis(priv->mdev, ipriv->qp.qpn, &priv->tisn[0]); err = mlx5i_create_tis(priv->mdev, ipriv->qp.qpn, &priv->tisn[0][0]);
if (err) { if (err) {
mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err); mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err);
goto err_destroy_underlay_qp; goto err_destroy_underlay_qp;
...@@ -296,7 +296,7 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv) ...@@ -296,7 +296,7 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv)
{ {
struct mlx5i_priv *ipriv = priv->ppriv; struct mlx5i_priv *ipriv = priv->ppriv;
mlx5e_destroy_tis(priv->mdev, priv->tisn[0]); mlx5e_destroy_tis(priv->mdev, priv->tisn[0][0]);
mlx5i_destroy_underlay_qp(priv->mdev, &ipriv->qp); mlx5i_destroy_underlay_qp(priv->mdev, &ipriv->qp);
} }
......
...@@ -210,7 +210,7 @@ static int mlx5i_pkey_open(struct net_device *netdev) ...@@ -210,7 +210,7 @@ static int mlx5i_pkey_open(struct net_device *netdev)
goto err_unint_underlay_qp; goto err_unint_underlay_qp;
} }
err = mlx5i_create_tis(mdev, ipriv->qp.qpn, &epriv->tisn[0]); err = mlx5i_create_tis(mdev, ipriv->qp.qpn, &epriv->tisn[0][0]);
if (err) { if (err) {
mlx5_core_warn(mdev, "create child tis failed, %d\n", err); mlx5_core_warn(mdev, "create child tis failed, %d\n", err);
goto err_remove_rx_uderlay_qp; goto err_remove_rx_uderlay_qp;
...@@ -228,7 +228,7 @@ static int mlx5i_pkey_open(struct net_device *netdev) ...@@ -228,7 +228,7 @@ static int mlx5i_pkey_open(struct net_device *netdev)
return 0; return 0;
err_clear_state_opened_flag: err_clear_state_opened_flag:
mlx5e_destroy_tis(mdev, epriv->tisn[0]); mlx5e_destroy_tis(mdev, epriv->tisn[0][0]);
err_remove_rx_uderlay_qp: err_remove_rx_uderlay_qp:
mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qp.qpn); mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qp.qpn);
err_unint_underlay_qp: err_unint_underlay_qp:
...@@ -257,7 +257,7 @@ static int mlx5i_pkey_close(struct net_device *netdev) ...@@ -257,7 +257,7 @@ static int mlx5i_pkey_close(struct net_device *netdev)
mlx5i_uninit_underlay_qp(priv); mlx5i_uninit_underlay_qp(priv);
mlx5e_deactivate_priv_channels(priv); mlx5e_deactivate_priv_channels(priv);
mlx5e_close_channels(&priv->channels); mlx5e_close_channels(&priv->channels);
mlx5e_destroy_tis(mdev, priv->tisn[0]); mlx5e_destroy_tis(mdev, priv->tisn[0][0]);
unlock: unlock:
mutex_unlock(&priv->state_lock); mutex_unlock(&priv->state_lock);
return 0; return 0;
......
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