From 38ddb456be9e044a682b789f762d890de9b90b69 Mon Sep 17 00:00:00 2001
From: Leon Romanovsky <leonro@nvidia.com>
Date: Mon, 17 Feb 2025 04:20:36 -0500
Subject: [PATCH 1/2] net/mlx5e: Don't update neigh entries in IPsec ESN
 overlap

ESN overlap causes to rebuild all IPsec internal attributes, however it
triggers the following kernel splat. That warning is caused due to
access to FW command interface which can sleep while being in atomic
context.

However, there is no need to update neigh entries at all as during ESN
overlap they are not changing, so simply skip such update.

 BUG: scheduling while atomic: kworker/u64:4/1831/0x00000200
 Modules linked in:
 CPU: 10 UID: 0 PID: 1831 Comm: kworker/u64:4 Not tainted 6.14.0-rc1 #14
 Hardware name: https://www.mellanox.com BlueField-3 DPU/BlueField-3 DPU, BIOS 4.9.1.13442 Dec  3 2024
 Workqueue: mlx5e_ipsec: eth%d mlx5e_ipsec_handle_event
 Call trace:
  show_stack+0x20/0x38 (C)
  dump_stack_lvl+0x74/0x90
  dump_stack+0x18/0x28
  __schedule_bug+0x5c/0x80
  __schedule+0x6c0/0x800
  schedule+0x30/0x100
  schedule_timeout+0x80/0x108
  __wait_for_common+0xd4/0x240
  wait_for_completion_timeout+0x28/0x40
  cmd_exec+0x810/0xbd8
  mlx5_cmd_do+0x38/0x88
  mlx5_cmd_exec+0x2c/0x60
  mlx5_query_nic_vport_mac_address+0x90/0xe8
  mlx5_query_mac_address+0x24/0x38
  mlx5e_ipsec_build_accel_xfrm_attrs+0x3d4/0x528
  mlx5e_ipsec_update_esn_state+0x88/0x170
  mlx5e_ipsec_handle_event+0xa8/0x360
  process_one_work+0x174/0x3d0
  worker_thread+0x290/0x478
  kthread+0x108/0x1e8
  ret_from_fork+0x10/0x20

Fixes: 37a417ca911a ("net/mlx5e: Support IPsec RX packet offload in tunnel mode")
Reported-by: Alexandre Cassen <acassen@corp.free.fr>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c    | 13 +++++++++----
 .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h    |  3 ++-
 .../mellanox/mlx5/core/en_accel/ipsec_offload.c     |  2 +-
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
index 135a64294d2a..e4ddc51aac85 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -333,7 +333,8 @@ static void mlx5e_ipsec_state_mask(struct mlx5e_ipsec_addr *addrs)
 }
 
 void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
-					struct mlx5_accel_esp_xfrm_attrs *attrs)
+					struct mlx5_accel_esp_xfrm_attrs *attrs,
+					bool update)
 {
 	struct xfrm_state *x = sa_entry->x;
 	struct aes_gcm_keymat *aes_gcm = &attrs->aes_gcm;
@@ -422,7 +423,11 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
 	attrs->mode = x->props.mode;
 
 	mlx5e_ipsec_init_limits(sa_entry, attrs);
-	mlx5e_ipsec_init_macs(sa_entry, attrs);
+	if (!update)
+		/* There is no need to get MACs as they are not changing
+		 * during ESN overlap.
+		 */
+		mlx5e_ipsec_init_macs(sa_entry, attrs);
 
 	if (x->encap) {
 		attrs->encap = true;
@@ -752,7 +757,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
 
 	/* check esn */
 	mlx5e_ipsec_update_esn_state(sa_entry);
-	mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &sa_entry->attrs);
+	mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &sa_entry->attrs, false);
 
 	err = mlx5_ipsec_create_work(sa_entry);
 	if (err)
@@ -994,7 +999,7 @@ static void mlx5e_xfrm_advance_esn_state(struct xfrm_state *x)
 
 	sa_entry_shadow = work->data;
 	memset(sa_entry_shadow, 0x00, sizeof(*sa_entry_shadow));
-	mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &sa_entry_shadow->attrs);
+	mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &sa_entry_shadow->attrs, true);
 	queue_work(sa_entry->ipsec->wq, &work->work);
 }
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
index a63c2289f8af..d2b5143dc5be 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
@@ -336,7 +336,8 @@ void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv,
 				     void *ipsec_stats);
 
 void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
-					struct mlx5_accel_esp_xfrm_attrs *attrs);
+					struct mlx5_accel_esp_xfrm_attrs *attrs,
+					bool update);
 void mlx5e_ipsec_handle_mpv_event(int event, struct mlx5e_priv *slave_priv,
 				  struct mlx5e_priv *master_priv);
 void mlx5e_ipsec_send_event(struct mlx5e_priv *priv, int event);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
index 820debf3fbbf..b1e30448e346 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
@@ -324,7 +324,7 @@ static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry,
 		sa_entry->esn_state.overlap = 1;
 	}
 
-	mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &attrs);
+	mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &attrs, true);
 
 	/* It is safe to execute the modify below unlocked since the only flows
 	 * that could affect this HW object, are create, destroy and this work.
-- 
2.25.1

