[net 09/10] net/mlx5e: Call synchronize_net outside of deactivating a queue
From: Saeed Mahameed <saeed@kernel.org>
Date: 2021-11-19 19:58:48
Subsystem:
mellanox ethernet driver (mlx5e), mellanox mlx5 core vpi driver, networking drivers, the rest · Maintainers:
Saeed Mahameed, Tariq Toukan, Mark Bloch, Leon Romanovsky, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Saeed Mahameed <saeedm@nvidia.com>
This patch moves synchronize_net outside of queue deactivate functions.
It prepares the code for the following fix that will convert to calling
synchronize_net only once when deactivating channels.
This patch also reduces the number of synchronize_net calls by squashing
together the calls in mlx5e_deactivate_channel, however, the real
reduction will happen in the next patch.
Also, mlx5e_deactivate_txqsq got separated into two functions, and
mlx5e_qos_deactivate_queues got separated into two sections and
to make it possible to move synchronize_net outside.
Fixes: 9c25a22dfb00 ("net/mlx5e: Use synchronize_rcu to sync with NAPI")
Signed-off-by: Lama Kayal <redacted>
Signed-off-by: Maxim Mikityanskiy <redacted>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 6 ++-
.../net/ethernet/mellanox/mlx5/core/en/ptp.c | 16 ++++---
.../net/ethernet/mellanox/mlx5/core/en/qos.c | 30 ++++++++-----
.../net/ethernet/mellanox/mlx5/core/en/qos.h | 2 +-
.../mellanox/mlx5/core/en/reporter_rx.c | 3 ++
.../mellanox/mlx5/core/en/reporter_tx.c | 3 +-
.../ethernet/mellanox/mlx5/core/en/xsk/pool.c | 2 +
.../net/ethernet/mellanox/mlx5/core/en_main.c | 44 ++++++++++++-------
8 files changed, 71 insertions(+), 35 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index a0a5d6321098..837354118df8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h@@ -1077,8 +1077,10 @@ int mlx5e_open_txqsq(struct mlx5e_channel *c, u32 tisn, int txq_ix, struct mlx5e_params *params, struct mlx5e_sq_param *param, struct mlx5e_txqsq *sq, int tc, u16 qos_queue_group_id, struct mlx5e_sq_stats *sq_stats); -void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq); -void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq); +void mlx5e_enable_txqsq(struct mlx5e_txqsq *sq); +void mlx5e_start_txqsq(struct mlx5e_txqsq *sq); +void mlx5e_disable_txqsq(struct mlx5e_txqsq *sq); +void mlx5e_stop_txqsq(struct mlx5e_txqsq *sq); void mlx5e_free_txqsq(struct mlx5e_txqsq *sq); void mlx5e_tx_disable_queue(struct netdev_queue *txq); int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
index 18d542b1c5cb..f190c5437294 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c@@ -731,8 +731,10 @@ void mlx5e_ptp_activate_channel(struct mlx5e_ptp *c) napi_enable(&c->napi); if (test_bit(MLX5E_PTP_STATE_TX, c->state)) { - for (tc = 0; tc < c->num_tc; tc++) - mlx5e_activate_txqsq(&c->ptpsq[tc].txqsq); + for (tc = 0; tc < c->num_tc; tc++) { + mlx5e_enable_txqsq(&c->ptpsq[tc].txqsq); + mlx5e_start_txqsq(&c->ptpsq[tc].txqsq); + } } if (test_bit(MLX5E_PTP_STATE_RX, c->state)) { mlx5e_ptp_rx_set_fs(c->priv);
@@ -748,10 +750,14 @@ void mlx5e_ptp_deactivate_channel(struct mlx5e_ptp *c) mlx5e_deactivate_rq(&c->rq); if (test_bit(MLX5E_PTP_STATE_TX, c->state)) { - for (tc = 0; tc < c->num_tc; tc++) - mlx5e_deactivate_txqsq(&c->ptpsq[tc].txqsq); - } + for (tc = 0; tc < c->num_tc; tc++) { + mlx5e_disable_txqsq(&c->ptpsq[tc].txqsq); + /* Sync with NAPI to prevent netif_tx_wake_queue. */ + synchronize_net(); + mlx5e_stop_txqsq(&c->ptpsq[tc].txqsq); + } + } napi_disable(&c->napi); }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
index 50977f01a050..869d5b3a38cc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c@@ -284,7 +284,8 @@ static void mlx5e_activate_qos_sq(struct mlx5e_priv *priv, struct mlx5e_qos_node smp_wmb(); qos_dbg(priv->mdev, "Activate QoS SQ qid %u\n", node->qid); - mlx5e_activate_txqsq(sq); + mlx5e_enable_txqsq(sq); + mlx5e_start_txqsq(sq); } static void mlx5e_deactivate_qos_sq(struct mlx5e_priv *priv, u16 qid)
@@ -296,8 +297,9 @@ static void mlx5e_deactivate_qos_sq(struct mlx5e_priv *priv, u16 qid) return; qos_dbg(priv->mdev, "Deactivate QoS SQ qid %u\n", qid); - mlx5e_deactivate_txqsq(sq); - + mlx5e_disable_txqsq(sq); + synchronize_net(); + mlx5e_stop_txqsq(sq); /* The queue is disabled, no synchronization with datapath is needed. */ priv->txq2sq[mlx5e_qid_from_qos(&priv->channels, qid)] = NULL; }
@@ -431,7 +433,7 @@ void mlx5e_qos_activate_queues(struct mlx5e_priv *priv) } } -void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c) +void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c, bool finalize) { struct mlx5e_params *params = &c->priv->channels.params; struct mlx5e_txqsq __rcu **qos_sqs;
@@ -448,12 +450,15 @@ void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c) sq = mlx5e_state_dereference(c->priv, qos_sqs[i]); if (!sq) /* Handle the case when the SQ failed to open. */ continue; - - qos_dbg(c->mdev, "Deactivate QoS SQ qid %u\n", qid); - mlx5e_deactivate_txqsq(sq); - - /* The queue is disabled, no synchronization with datapath is needed. */ - c->priv->txq2sq[mlx5e_qid_from_qos(&c->priv->channels, qid)] = NULL; + if (finalize) { + qos_dbg(c->mdev, "Finalize QoS SQ qid %u\n", qid); + mlx5e_stop_txqsq(sq); + /* The queue is disabled, no synchronization with datapath is needed. */ + c->priv->txq2sq[mlx5e_qid_from_qos(&c->priv->channels, qid)] = NULL; + } else { + qos_dbg(c->mdev, "Deactivate QoS SQ qid %u\n", qid); + mlx5e_disable_txqsq(sq); + } } }
@@ -462,7 +467,10 @@ static void mlx5e_qos_deactivate_all_queues(struct mlx5e_channels *chs) int i; for (i = 0; i < chs->num; i++) - mlx5e_qos_deactivate_queues(chs->c[i]); + mlx5e_qos_deactivate_queues(chs->c[i], false); + synchronize_net(); + for (i = 0; i < chs->num; i++) + mlx5e_qos_deactivate_queues(chs->c[i], true); } /* HTB API */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.h b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.h
index b7558907ba20..bf294288c1ea 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.h@@ -23,7 +23,7 @@ struct mlx5e_txqsq *mlx5e_get_sq(struct mlx5e_priv *priv, int qid); /* SQ lifecycle */ int mlx5e_qos_open_queues(struct mlx5e_priv *priv, struct mlx5e_channels *chs); void mlx5e_qos_activate_queues(struct mlx5e_priv *priv); -void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c); +void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c, bool finalize); void mlx5e_qos_close_queues(struct mlx5e_channel *c); /* HTB API */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
index 74086eb556ae..98959ffa5efa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c@@ -84,11 +84,13 @@ static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx) goto out; mlx5e_deactivate_rq(rq); + synchronize_net(); /* Sync with NAPI. */ err = mlx5e_wait_for_icosq_flush(icosq); if (err) goto out; mlx5e_deactivate_icosq(icosq); + synchronize_net(); /* Sync with NAPI. */ /* At this point, both the rq and the icosq are disabled */
@@ -134,6 +136,7 @@ static int mlx5e_rx_reporter_err_rq_cqe_recover(void *ctx) int err; mlx5e_deactivate_rq(rq); + synchronize_net(); /* Sync with NAPI. */ mlx5e_free_rx_descs(rq); err = mlx5e_rq_to_ready(rq, MLX5_RQC_STATE_ERR);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
index 4f4bc8726ec4..262deeb80e5b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c@@ -80,7 +80,8 @@ static int mlx5e_tx_reporter_err_cqe_recover(void *ctx) mlx5e_reset_txqsq_cc_pc(sq); sq->stats->recover++; clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state); - mlx5e_activate_txqsq(sq); + mlx5e_enable_txqsq(sq); + mlx5e_start_txqsq(sq); return 0; out:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c
index 7b562d2c8a19..4c7bf4e1bfee 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c@@ -130,6 +130,7 @@ static int mlx5e_xsk_enable_locked(struct mlx5e_priv *priv, err_deactivate: mlx5e_deactivate_xsk(c); + synchronize_net(); /* Sync with NAPI. */ mlx5e_close_xsk(c); err_remove_pool:
@@ -171,6 +172,7 @@ static int mlx5e_xsk_disable_locked(struct mlx5e_priv *priv, u16 ix) c = priv->channels.c[ix]; mlx5e_rx_res_xsk_deactivate(priv->rx_res, ix); mlx5e_deactivate_xsk(c); + synchronize_net(); /* Sync with NAPI. */ mlx5e_close_xsk(c); remove_pool:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 6914fc17277a..1fb0d9b70301 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c@@ -1081,7 +1081,6 @@ void mlx5e_activate_rq(struct mlx5e_rq *rq) void mlx5e_deactivate_rq(struct mlx5e_rq *rq) { clear_bit(MLX5E_RQ_STATE_ENABLED, &rq->state); - synchronize_net(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */ } void mlx5e_close_rq(struct mlx5e_rq *rq)
@@ -1513,14 +1512,18 @@ int mlx5e_open_txqsq(struct mlx5e_channel *c, u32 tisn, int txq_ix, return err; } -void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) +void mlx5e_enable_txqsq(struct mlx5e_txqsq *sq) { sq->txq = netdev_get_tx_queue(sq->netdev, sq->txq_ix); set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); +} + +void mlx5e_start_txqsq(struct mlx5e_txqsq *sq) +{ + sq->txq = netdev_get_tx_queue(sq->netdev, sq->txq_ix); netdev_tx_reset_queue(sq->txq); netif_tx_start_queue(sq->txq); } - void mlx5e_tx_disable_queue(struct netdev_queue *txq) { __netif_tx_lock_bh(txq);
@@ -1528,13 +1531,18 @@ void mlx5e_tx_disable_queue(struct netdev_queue *txq) __netif_tx_unlock_bh(txq); } -void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq) +void mlx5e_disable_txqsq(struct mlx5e_txqsq *sq) { - struct mlx5_wq_cyc *wq = &sq->wq; - clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); - synchronize_net(); /* Sync with NAPI to prevent netif_tx_wake_queue. */ +} + +void mlx5e_stop_txqsq(struct mlx5e_txqsq *sq) +{ + struct mlx5_wq_cyc *wq = &sq->wq; + /* The SQ must be deactivated, and synchronize_rcu must be called before + * this function to prevent netif_tx_wake_queue from reenabling the SQ. + */ mlx5e_tx_disable_queue(sq->txq); /* last doorbell out, godspeed .. */
@@ -1617,7 +1625,6 @@ void mlx5e_activate_icosq(struct mlx5e_icosq *icosq) void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq) { clear_bit(MLX5E_SQ_STATE_ENABLED, &icosq->state); - synchronize_net(); /* Sync with NAPI. */ } void mlx5e_close_icosq(struct mlx5e_icosq *sq)
@@ -1699,7 +1706,6 @@ void mlx5e_activate_xdpsq(struct mlx5e_xdpsq *sq) void mlx5e_deactivate_xdpsq(struct mlx5e_xdpsq *sq) { clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); - synchronize_net(); /* Sync with NAPI. */ } void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq)
@@ -2251,8 +2257,10 @@ static void mlx5e_activate_channel(struct mlx5e_channel *c) napi_enable(&c->napi); - for (tc = 0; tc < c->num_tc; tc++) - mlx5e_activate_txqsq(&c->sq[tc]); + for (tc = 0; tc < c->num_tc; tc++) { + mlx5e_enable_txqsq(&c->sq[tc]); + mlx5e_start_txqsq(&c->sq[tc]); + } mlx5e_activate_icosq(&c->icosq); mlx5e_activate_icosq(&c->async_icosq); if (c->xdp)
@@ -2277,10 +2285,16 @@ static void mlx5e_deactivate_channel(struct mlx5e_channel *c) mlx5e_deactivate_xdpsq(&c->rq_xdpsq); mlx5e_deactivate_icosq(&c->async_icosq); mlx5e_deactivate_icosq(&c->icosq); - for (tc = 0; tc < c->num_tc; tc++) - mlx5e_deactivate_txqsq(&c->sq[tc]); - mlx5e_qos_deactivate_queues(c); - + synchronize_net(); /* Sync with NAPI. */ + for (tc = 0; tc < c->num_tc; tc++) { + mlx5e_disable_txqsq(&c->sq[tc]); + /* Sync with NAPI to prevent netif_tx_wake_queue. */ + synchronize_net(); + mlx5e_stop_txqsq(&c->sq[tc]); + } + mlx5e_qos_deactivate_queues(c, false); + synchronize_net(); + mlx5e_qos_deactivate_queues(c, true); napi_disable(&c->napi); }
--
2.31.1