]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/mlx5e: IPsec, fix ASO poll timeout with read_poll_timeout_atomic()
authorGal Pressman <gal@nvidia.com>
Thu, 9 Apr 2026 20:28:52 +0000 (23:28 +0300)
committerJakub Kicinski <kuba@kernel.org>
Sun, 12 Apr 2026 21:37:08 +0000 (14:37 -0700)
The do-while poll loop uses jiffies for its timeout:
  expires = jiffies + msecs_to_jiffies(10);

jiffies is sampled at an arbitrary point within the current tick, so the
first partial tick contributes anywhere from a full tick down to nearly
zero real time. For small msecs_to_jiffies() results this is
significant, the effective poll window can be much shorter than the
requested 10ms, and in the worst case the loop exits after a single
iteration (e.g., when HZ=100), well before the device has delivered the
CQE.

Replace the loop with read_poll_timeout_atomic(), which counts elapsed
time via udelay() accounting rather than jiffies, guaranteeing the full
poll window regardless of HZ.

Additionally, read_poll_timeout_atomic() executes the poll operation one
more time after the timeout has expired, giving the CQE a final chance
to be detected. The old do-while loop could exit without a final poll if
the timeout expired during the udelay() between iterations.

Fixes: 76e463f6508b ("net/mlx5e: Overcome slow response for first IPsec ASO WQE")
Signed-off-by: Gal Pressman <gal@nvidia.com>
Reviewed-by: Jianbo Liu <jianbol@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260409202852.158059-3-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c

index 05faad5083d9d5df7cbef885e34d89cc4d83dca7..145677ce96408f71fa0ffdce588e9f086f6104ff 100644 (file)
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /* Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. */
 
+#include <linux/iopoll.h>
+
 #include "mlx5_core.h"
 #include "en.h"
 #include "ipsec.h"
@@ -592,7 +594,6 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
        struct mlx5_wqe_aso_ctrl_seg *ctrl;
        struct mlx5e_hw_objs *res;
        struct mlx5_aso_wqe *wqe;
-       unsigned long expires;
        u8 ds_cnt;
        int ret;
 
@@ -614,13 +615,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
        mlx5e_ipsec_aso_copy(ctrl, data);
 
        mlx5_aso_post_wqe(aso->aso, false, &wqe->ctrl);
-       expires = jiffies + msecs_to_jiffies(10);
-       do {
-               ret = mlx5_aso_poll_cq(aso->aso, false);
-               if (ret)
-                       /* We are in atomic context */
-                       udelay(10);
-       } while (ret && time_is_after_jiffies(expires));
+       read_poll_timeout_atomic(mlx5_aso_poll_cq, ret, !ret, 10,
+                                10 * USEC_PER_MSEC, false, aso->aso, false);
        if (!ret)
                memcpy(sa_entry->ctx, aso->ctx, MLX5_ST_SZ_BYTES(ipsec_aso));
        spin_unlock_bh(&aso->lock);