From: Yonatan Nachum <ynachum@amazon.com>
To: <jgg@nvidia.com>, <leon@kernel.org>, <linux-rdma@vger.kernel.org>
Cc: <sleybo@amazon.com>, <matua@amazon.com>, <gal.pressman@linux.dev>,
"Yonatan Nachum" <ynachum@amazon.com>,
Michael Margolin <mrgolin@amazon.com>,
Tom Sela <tomsela@amazon.com>
Subject: [PATCH for-rc v2] RDMA/efa: Fix race between admin command timeout and completion
Date: Mon, 12 Oct 2026 16:51:13 +0000 [thread overview]
Message-ID: <20261012165113.576899-1-ynachum@amazon.com> (raw)
An admin command that times out can race with the interrupt handler
processing its completion, in two ways.
The timeout path releases the completion context without synchronizing
against the handler. A handler that has already seen the command as
submitted then copies the CQE into the caller's response buffer after
the waiter returned and that buffer went out of scope.
The waiter can also observe the command as completed before the CQE was
copied, since the status is published first. It decodes its own
uninitialized response buffer, returns success with garbage contents and
leaks stack data to the caller. Both wait paths read the status without
the CQ lock.
Add a timed-out state and publish it under the CQ lock in both wait
paths before returning, so the handler, which only completes commands in
submitted state, cannot act on an abandoned context. In the interrupt
wait path test the return value of the wait instead of the status: the
handler signals the completion after copying the CQE, so a successful
wait implies a valid response. Read the status in the polling wait path
inside the critical section that drains the CQ, which also lets a
completion arriving on the last iteration be honored instead of reported
as a timeout.
Fixes: 0420e542569b ("RDMA/efa: Implement functions that submit and complete admin commands")
Reviewed-by: Michael Margolin <mrgolin@amazon.com>
Reviewed-by: Tom Sela <tomsela@amazon.com>
Signed-off-by: Yonatan Nachum <ynachum@amazon.com>
---
Changelog:
v2:
* Read the completion status under the CQ lock in the polling path
instead of only taking the lock around the timed-out store.
* Use the wait_for_completion_timeout() return value in the interrupt
path instead of reading the status unlocked to determine whether the
command timed out.
v1: https://lore.kernel.org/all/20260901113016.581935-1-ynachum@amazon.com/
drivers/infiniband/hw/efa/efa_com.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
index 04c6d63c449e..9c59d127e1e0 100644
--- a/drivers/infiniband/hw/efa/efa_com.c
+++ b/drivers/infiniband/hw/efa/efa_com.c
@@ -41,6 +41,7 @@ enum efa_cmd_status {
EFA_CMD_ALLOCATED,
EFA_CMD_SUBMITTED,
EFA_CMD_COMPLETED,
+ EFA_CMD_TIMED_OUT,
};
struct efa_comp_ctx {
@@ -591,6 +592,7 @@ static int efa_com_comp_status_to_errno(u8 comp_status)
static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_ctx,
struct efa_com_admin_queue *aq)
{
+ bool comp_timeout = false;
unsigned long timeout;
unsigned long flags;
@@ -599,12 +601,19 @@ static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_c
while (1) {
spin_lock_irqsave(&aq->cq.lock, flags);
efa_com_handle_admin_completion(aq);
- spin_unlock_irqrestore(&aq->cq.lock, flags);
-
- if (comp_ctx->status != EFA_CMD_SUBMITTED)
+ if (comp_ctx->status != EFA_CMD_SUBMITTED) {
+ spin_unlock_irqrestore(&aq->cq.lock, flags);
break;
+ }
if (time_is_before_jiffies(timeout)) {
+ comp_ctx->status = EFA_CMD_TIMED_OUT;
+ comp_timeout = true;
+ }
+
+ spin_unlock_irqrestore(&aq->cq.lock, flags);
+
+ if (comp_timeout) {
ibdev_err_ratelimited(
aq->efa_dev,
"Wait for completion (polling) timeout\n");
@@ -625,10 +634,11 @@ static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_c
static int efa_com_wait_and_process_admin_cq_interrupts(struct efa_comp_ctx *comp_ctx,
struct efa_com_admin_queue *aq)
{
- unsigned long flags;
+ unsigned long flags, remaining_jiffies;
+ bool completed;
- wait_for_completion_timeout(&comp_ctx->wait_event,
- usecs_to_jiffies(aq->completion_timeout));
+ remaining_jiffies = wait_for_completion_timeout(
+ &comp_ctx->wait_event, usecs_to_jiffies(aq->completion_timeout));
/*
* In case the command wasn't completed find out the root cause.
@@ -636,14 +646,16 @@ static int efa_com_wait_and_process_admin_cq_interrupts(struct efa_comp_ctx *com
* 1) No completion (timeout reached)
* 2) There is completion but the device didn't get any msi-x interrupt.
*/
- if (comp_ctx->status == EFA_CMD_SUBMITTED) {
+ if (remaining_jiffies == 0) {
spin_lock_irqsave(&aq->cq.lock, flags);
efa_com_handle_admin_completion(aq);
+ completed = (comp_ctx->status == EFA_CMD_COMPLETED);
+ comp_ctx->status = EFA_CMD_TIMED_OUT;
spin_unlock_irqrestore(&aq->cq.lock, flags);
atomic64_inc(&aq->stats.no_completion);
- if (comp_ctx->status == EFA_CMD_COMPLETED)
+ if (completed)
ibdev_err_ratelimited(
aq->efa_dev,
"The device sent a completion but the driver didn't receive any MSI-X interrupt for admin cmd %s(%d) status %d (id: %d, sq producer: %d, sq consumer: %d, cq consumer: %d)\n",
--
2.50.1
next reply other threads:[~2026-10-12 16:51 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 16:51 Yonatan Nachum [this message]
2026-10-12 16:57 ` [PATCH for-rc v2] RDMA/efa: Fix race between admin command timeout and completion sashiko-bot
2026-10-13 10:53 ` Leon Romanovsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261012165113.576899-1-ynachum@amazon.com \
--to=ynachum@amazon.com \
--cc=gal.pressman@linux.dev \
--cc=jgg@nvidia.com \
--cc=leon@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=matua@amazon.com \
--cc=mrgolin@amazon.com \
--cc=sleybo@amazon.com \
--cc=tomsela@amazon.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox