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

net/mlx5: Fix misidentification of write combining CQE during poll loop



The write combining completion poll loop uses usleep_range() which can
sleep much longer than requested due to scheduler latency. Under load,
we witnessed a 20ms+ delay until the process was rescheduled, causing
the jiffies based timeout to expire while the thread is sleeping.

The original do-while loop structure (poll, sleep, check timeout) would
exit without a final poll when waking after timeout, missing a CQE that
arrived during sleep.

Instead of the open-coded while loop, use the kernel's poll_timeout_us()
which always performs an additional check after the sleep expiration,
and is less error-prone.

Note: poll_timeout_us() doesn't accept a sleep range, by passing 10
sleep_us the sleep range effectively changes from 2-10 to 3-10 usecs.

Fixes: d98995b4 ("net/mlx5: Reimplement write combining test")
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>
Reviewed-by: default avatarJacob Keller <Jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260218072904.1764634-4-tariqt@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ae3cb71e
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
// Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.

#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mlx5/transobj.h>
#include "lib/clock.h"
#include "mlx5_core.h"
@@ -15,7 +16,7 @@
#define TEST_WC_NUM_WQES 255
#define TEST_WC_LOG_CQ_SZ (order_base_2(TEST_WC_NUM_WQES))
#define TEST_WC_SQ_LOG_WQ_SZ TEST_WC_LOG_CQ_SZ
#define TEST_WC_POLLING_MAX_TIME_JIFFIES msecs_to_jiffies(100)
#define TEST_WC_POLLING_MAX_TIME_USEC (100 * USEC_PER_MSEC)

struct mlx5_wc_cq {
	/* data path - accessed per cqe */
@@ -359,7 +360,6 @@ static int mlx5_wc_poll_cq(struct mlx5_wc_sq *sq)
static void mlx5_core_test_wc(struct mlx5_core_dev *mdev)
{
	unsigned int offset = 0;
	unsigned long expires;
	struct mlx5_wc_sq *sq;
	int i, err;

@@ -389,13 +389,9 @@ static void mlx5_core_test_wc(struct mlx5_core_dev *mdev)

	mlx5_wc_post_nop(sq, &offset, true);

	expires = jiffies + TEST_WC_POLLING_MAX_TIME_JIFFIES;
	do {
		err = mlx5_wc_poll_cq(sq);
		if (err)
			usleep_range(2, 10);
	} while (mdev->wc_state == MLX5_WC_STATE_UNINITIALIZED &&
		 time_is_after_jiffies(expires));
	poll_timeout_us(mlx5_wc_poll_cq(sq),
			mdev->wc_state != MLX5_WC_STATE_UNINITIALIZED, 10,
			TEST_WC_POLLING_MAX_TIME_USEC, false);

	mlx5_wc_destroy_sq(sq);