Commit edccdd1e authored by Gal Pressman's avatar Gal Pressman Committed by Jakub Kicinski
Browse files

net/mlx5e: IPsec, fix ASO poll timeout with read_poll_timeout_atomic()



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: 76e463f6 ("net/mlx5e: Overcome slow response for first IPsec ASO WQE")
Signed-off-by: default avatarGal Pressman <gal@nvidia.com>
Reviewed-by: default avatarJianbo Liu <jianbol@nvidia.com>
Signed-off-by: default avatarTariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260409202852.158059-3-tariqt@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 9994ad4d
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
// 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);