151 lines
4.9 KiB
Diff
151 lines
4.9 KiB
Diff
From d17c81e1bebf992831b10750cc1ee7c6fdc04339 Mon Sep 17 00:00:00 2001
|
|
From: Kamal Heib <kheib@redhat.com>
|
|
Date: Thu, 16 Apr 2026 18:03:18 -0400
|
|
Subject: [PATCH] net/mlx5e: Implement queue mgmt ops and single channel swap
|
|
|
|
JIRA: https://redhat.atlassian.net/browse/RHEL-169055
|
|
|
|
commit b2588ea40ec9472688289c1a644627c0f4a1f33f
|
|
Author: Saeed Mahameed <saeedm@nvidia.com>
|
|
Date: Mon Jun 16 17:14:39 2025 +0300
|
|
|
|
net/mlx5e: Implement queue mgmt ops and single channel swap
|
|
|
|
The bulk of the work is done in mlx5e_queue_mem_alloc, where we allocate
|
|
and create the new channel resources, similar to
|
|
mlx5e_safe_switch_params, but here we do it for a single channel using
|
|
existing params, sort of a clone channel.
|
|
To swap the old channel with the new one, we deactivate and close the
|
|
old channel then replace it with the new one, since the swap procedure
|
|
doesn't fail in mlx5, we do it all in one place (mlx5e_queue_start).
|
|
|
|
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
|
|
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
|
|
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
|
|
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
|
|
Acked-by: Mina Almasry <almasrymina@google.com>
|
|
Link: https://patch.msgid.link/20250616141441.1243044-11-mbloch@nvidia.com
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
|
Signed-off-by: Kamal Heib <kheib@redhat.com>
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
|
|
index 59e845367cfd..9330d90c1f03 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
|
|
@@ -5479,6 +5479,103 @@ static const struct netdev_stat_ops mlx5e_stat_ops = {
|
|
.get_base_stats = mlx5e_get_base_stats,
|
|
};
|
|
|
|
+struct mlx5_qmgmt_data {
|
|
+ struct mlx5e_channel *c;
|
|
+ struct mlx5e_channel_param cparam;
|
|
+};
|
|
+
|
|
+static int mlx5e_queue_mem_alloc(struct net_device *dev, void *newq,
|
|
+ int queue_index)
|
|
+{
|
|
+ struct mlx5_qmgmt_data *new = (struct mlx5_qmgmt_data *)newq;
|
|
+ struct mlx5e_priv *priv = netdev_priv(dev);
|
|
+ struct mlx5e_channels *chs = &priv->channels;
|
|
+ struct mlx5e_params params = chs->params;
|
|
+ struct mlx5_core_dev *mdev;
|
|
+ int err;
|
|
+
|
|
+ mutex_lock(&priv->state_lock);
|
|
+ if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
|
|
+ err = -ENODEV;
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
+ if (queue_index >= chs->num) {
|
|
+ err = -ERANGE;
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
+ if (MLX5E_GET_PFLAG(&chs->params, MLX5E_PFLAG_TX_PORT_TS) ||
|
|
+ chs->params.ptp_rx ||
|
|
+ chs->params.xdp_prog ||
|
|
+ priv->htb) {
|
|
+ netdev_err(priv->netdev,
|
|
+ "Cloning channels with Port/rx PTP, XDP or HTB is not supported\n");
|
|
+ err = -EOPNOTSUPP;
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
+ mdev = mlx5_sd_ch_ix_get_dev(priv->mdev, queue_index);
|
|
+ err = mlx5e_build_channel_param(mdev, ¶ms, &new->cparam);
|
|
+ if (err)
|
|
+ goto unlock;
|
|
+
|
|
+ err = mlx5e_open_channel(priv, queue_index, ¶ms, NULL, &new->c);
|
|
+unlock:
|
|
+ mutex_unlock(&priv->state_lock);
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static void mlx5e_queue_mem_free(struct net_device *dev, void *mem)
|
|
+{
|
|
+ struct mlx5_qmgmt_data *data = (struct mlx5_qmgmt_data *)mem;
|
|
+
|
|
+ /* not supposed to happen since mlx5e_queue_start never fails
|
|
+ * but this is how this should be implemented just in case
|
|
+ */
|
|
+ if (data->c)
|
|
+ mlx5e_close_channel(data->c);
|
|
+}
|
|
+
|
|
+static int mlx5e_queue_stop(struct net_device *dev, void *oldq, int queue_index)
|
|
+{
|
|
+ /* In mlx5 a txq cannot be simply stopped in isolation, only restarted.
|
|
+ * mlx5e_queue_start does not fail, we stop the old queue there.
|
|
+ * TODO: Improve this.
|
|
+ */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int mlx5e_queue_start(struct net_device *dev, void *newq,
|
|
+ int queue_index)
|
|
+{
|
|
+ struct mlx5_qmgmt_data *new = (struct mlx5_qmgmt_data *)newq;
|
|
+ struct mlx5e_priv *priv = netdev_priv(dev);
|
|
+ struct mlx5e_channel *old;
|
|
+
|
|
+ mutex_lock(&priv->state_lock);
|
|
+
|
|
+ /* stop and close the old */
|
|
+ old = priv->channels.c[queue_index];
|
|
+ mlx5e_deactivate_priv_channels(priv);
|
|
+ /* close old before activating new, to avoid napi conflict */
|
|
+ mlx5e_close_channel(old);
|
|
+
|
|
+ /* start the new */
|
|
+ priv->channels.c[queue_index] = new->c;
|
|
+ mlx5e_activate_priv_channels(priv);
|
|
+ mutex_unlock(&priv->state_lock);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct netdev_queue_mgmt_ops mlx5e_queue_mgmt_ops = {
|
|
+ .ndo_queue_mem_size = sizeof(struct mlx5_qmgmt_data),
|
|
+ .ndo_queue_mem_alloc = mlx5e_queue_mem_alloc,
|
|
+ .ndo_queue_mem_free = mlx5e_queue_mem_free,
|
|
+ .ndo_queue_start = mlx5e_queue_start,
|
|
+ .ndo_queue_stop = mlx5e_queue_stop,
|
|
+};
|
|
+
|
|
static void mlx5e_build_nic_netdev(struct net_device *netdev)
|
|
{
|
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
|
@@ -5489,6 +5586,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
|
|
SET_NETDEV_DEV(netdev, mdev->device);
|
|
|
|
netdev->netdev_ops = &mlx5e_netdev_ops;
|
|
+ netdev->queue_mgmt_ops = &mlx5e_queue_mgmt_ops;
|
|
netdev->xdp_metadata_ops = &mlx5e_xdp_metadata_ops;
|
|
netdev->xsk_tx_metadata_ops = &mlx5e_xsk_tx_metadata_ops;
|
|
|
|
--
|
|
2.50.1 (Apple Git-155)
|
|
|