From: netdev-bot+sashiko@kernel.org
To: longli@microsoft.com
Cc: longli@kernel.org, kotaranov@microsoft.com, kuba@kernel.org,
davem@davemloft.net, pabeni@redhat.com, edumazet@google.com,
andrew+netdev@lunn.ch, jgg@ziepe.ca, leon@kernel.org,
haiyangz@microsoft.com, kys@microsoft.com, wei.liu@kernel.org,
decui@microsoft.com, shradhagupta@linux.microsoft.com,
horms@kernel.org, ernis@linux.microsoft.com,
stephen@networkplumber.org, shirazsaleem@microsoft.com,
netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next v5 2/4] net: mana: give each HWC message slot its own completion state
Date: Fri, 11 Sep 2026 06:53:22 +0000 [thread overview]
Message-ID: <178910960289.219967.5929065773405833614@kernel.org> (raw)
In-Reply-To: <20260908035201.402424-3-longli@microsoft.com>
Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider:
Critical: 0 · High: 0 (1) · Medium: 1 (1) · Low: 1
- [Medium] The commit message presents this patch as pure preparation
("Add per-slot locking, sender/response references and a responded…
- [Low] The new field comments added to struct hwc_caller_ctx in
include/net/mana/hw_channel.h describe a narrower contract than…
Pre-existing issues:
- [High] In this patch, mana_hwc_send_request()'s out: label latches
ctx->responded, clears output_buf and drops both the sender and the…
- [Medium] hwc->hwc_timeout is read and read-modify-written by senders in
process context (`wait_ms = hwc->hwc_timeout;` and `if…
--
net: mana: give each HWC message slot its own completion state
This adds a per-slot spinlock, a sender/response reference pair and a
responded flag to struct hwc_caller_ctx, makes ctx->error signed, and
withdraws the caller's response buffer once the sender stops waiting.
It also ignores a zero timeout value in a GDMA_QUERY_HWC_TIMEOUT reply.
No Link: tags in the commit header.
> diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
> index 88e92e94e2e90..6605e7a9c481b 100644
> --- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
> +++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
[ ... ]
> @@ -19,6 +21,17 @@ static int mana_hwc_get_msg_index(struct hw_channel_context *hwc, u16 *msg_id)
> index = find_first_zero_bit(hwc->inflight_msg_res.map,
> hwc->inflight_msg_res.size);
>
> + ctx = &hwc->caller_ctx[index];
> + reinit_completion(&ctx->comp_event);
> + /* Take both references (sender + handle_resp) before publishing the
> + * slot, so an early response cannot free it under the sender.
> + */
> + refcount_set(&ctx->refcnt, 2);
> + ctx->responded = false;
> + ctx->msg_id = index;
> + ctx->error = -EINPROGRESS;
> +
> + /* Publish the slot last, after it is fully initialised. */
> bitmap_set(hwc->inflight_msg_res.map, index, 1);
>
> spin_unlock_irqrestore(&r->lock, flags);
[ ... ]
> @@ -90,22 +110,35 @@ static void mana_hwc_handle_resp(struct hw_channel_context *hwc, u32 resp_len,
> }
>
> ctx = hwc->caller_ctx + msg_id;
> - err = mana_hwc_verify_resp_msg(ctx, resp_msg, resp_len);
> - if (err)
> - goto out;
>
> - ctx->status_code = resp_msg->status;
> + spin_lock(&ctx->lock);
>
> - memcpy(ctx->output_buf, resp_msg, resp_len);
> -out:
> + /* Honour a response only while the sender owns the slot (output_buf
> + * published) and has not already been answered; otherwise drop it as
> + * premature, stale or duplicate without touching the refcount.
> + */
> + if (!ctx->output_buf || ctx->responded) {
> + spin_unlock(&ctx->lock);
> + mana_hwc_post_rx_wqe(hwc->rxq, rx_req);
> + return;
> + }
> + ctx->responded = true;
[Severity: Medium]
Should this hunk carry a Fixes: tag rather than being described as
preparation?
The commit message says:
Add per-slot locking, sender/response references and a responded flag;
make ctx->error signed. Stop copying after buffer withdrawal or
completion.
"Stop copying after buffer withdrawal or completion" reads like a refactor
item, but at the baseline mana_hwc_send_request() released the message slot
on timeout while leaving ctx->output_buf and ctx->output_buflen pointing at
the caller's response buffer, which is usually on the caller's stack:
drivers/net/ethernet/microsoft/mana/gdma_main.c:mana_gd_query_hwc_timeout() {
struct gdma_query_hwc_timeout_resp resp = {};
...
err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp);
}
The baseline mana_hwc_handle_resp() then copied a late response into that
pointer as soon as the bit was set again by the next sender:
if (!test_bit(msg_id, hwc->inflight_msg_res.map)) {
...
}
ctx = hwc->caller_ctx + msg_id;
err = mana_hwc_verify_resp_msg(ctx, resp_msg, resp_len);
...
memcpy(ctx->output_buf, resp_msg, resp_len);
With HW_CHANNEL_VF_BOOTSTRAP_QUEUE_DEPTH == 1 the same index is always
reused, so the write lands in a stack frame that has already returned, and
the length check runs against the stale output_buflen.
Is the new output_buf test here, together with the ctx->output_buf = NULL
withdrawal in mana_hwc_send_request(), what closes that window? If so, would
a Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network
Adapter (MANA)") and a mention of the corruption in the changelog make this
visible to stable? The changelog notes the work was re-targeted from a "net
fixes-only posting" to net-next, which makes the fix easy to miss.
>
> err = mana_hwc_verify_resp_msg(ctx, resp_msg, resp_len);
> + if (!err) {
> + ctx->status_code = resp_msg->status;
> + memcpy(ctx->output_buf, resp_msg, resp_len);
> + }
> ctx->error = err;
>
> - /* Must post rx wqe before complete(), otherwise the next rx may
> - * hit no_wqe error.
> + /* Post RX WQE before completing — the next response may arrive
> + * immediately and needs a posted buffer.
> */
> mana_hwc_post_rx_wqe(hwc->rxq, rx_req);
> -
> complete(&ctx->comp_event);
> + spin_unlock(&ctx->lock);
> +
> + hwc_ctx_put(hwc, ctx);
> }
[ ... ]
> @@ -878,8 +925,11 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
> }
>
> ctx = hwc->caller_ctx + msg_id;
> +
> + spin_lock_irqsave(&ctx->lock, flags);
> ctx->output_buf = resp;
> ctx->output_buflen = resp_len;
> + spin_unlock_irqrestore(&ctx->lock, flags);
[ ... ]
> @@ -895,43 +945,108 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
> + wait_ms = hwc->hwc_timeout;
> if (!wait_for_completion_timeout(&ctx->comp_event,
> - (msecs_to_jiffies(hwc->hwc_timeout)))) {
> - if (hwc->hwc_timeout != 0)
> + msecs_to_jiffies(wait_ms))) {
> + /* Clear output_buf so a late response cannot write the caller's
> + * buffer, then check whether one already arrived
> + * (error != -EINPROGRESS).
> + */
> + spin_lock_irqsave(&ctx->lock, flags);
> + ctx->output_buf = NULL;
> + err = ctx->error;
> + status = ctx->status_code;
> + spin_unlock_irqrestore(&ctx->lock, flags);
[ ... ]
> out:
> - mana_hwc_put_msg_index(hwc, msg_id);
> + /* Error, no-wait teardown, or timeout: drop the sender's and the
> + * response-side references. Latch ->responded so a racing response
> + * is a no-op, and only drop the response-side ref if it has not.
> + */
> + ctx = hwc->caller_ctx + msg_id;
> + spin_lock_irqsave(&ctx->lock, flags);
> + ctx->output_buf = NULL;
> + drop_resp_ref = !ctx->responded;
> + ctx->responded = true;
> + spin_unlock_irqrestore(&ctx->lock, flags);
> + if (drop_resp_ref)
> + refcount_dec(&ctx->refcnt);
> + hwc_ctx_put(hwc, ctx);
> +done:
> return err;
> }
> diff --git a/include/net/mana/hw_channel.h b/include/net/mana/hw_channel.h
> index befa09674ce56..b377e221aa5c8 100644
> --- a/include/net/mana/hw_channel.h
> +++ b/include/net/mana/hw_channel.h
> @@ -171,8 +171,24 @@ struct hwc_caller_ctx {
> void *output_buf;
> u32 output_buflen;
>
> - u32 error; /* Linux error code */
> + int error; /* Linux error code (negative errno or 0) */
> u32 status_code;
> +
> + /* Protects output_buf against concurrent access from
> + * handle_resp() (CQ interrupt) and the sender timeout path.
> + */
> + spinlock_t lock;
> +
> + /* Tracks sender + handle_resp ownership. The last put
> + * (refcount reaches 0) releases the bitmap slot.
> + */
> + refcount_t refcnt;
> + u16 msg_id;
> +
> + /* Set by the first handle_resp(), or by the sender's timeout path,
> + * so a later or duplicate response is dropped.
> + */
> + bool responded;
> };
[Severity: Low]
These three comments look narrower than what hw_channel.c actually relies
on. Could they be extended?
The lock comment mentions output_buf only, but the out: block in
mana_hwc_send_request() also uses it to serialize ->responded and to decide
who owns the response-side reference:
spin_lock_irqsave(&ctx->lock, flags);
ctx->output_buf = NULL;
drop_resp_ref = !ctx->responded;
ctx->responded = true;
spin_unlock_irqrestore(&ctx->lock, flags);
and ctx->error / ctx->status_code are read and written under the same lock
in both mana_hwc_handle_resp() and mana_hwc_send_request().
The responded comment says it is set "by the first handle_resp(), or by the
sender's timeout path", but the out: block above is also reached from the
req_len > tx_wr->buf_len rejection, from mana_hwc_post_tx_wqe() failure, and
from the no-wait teardown path where hwc_timeout is 0.
The error comment says "Linux error code (negative errno or 0)", while
mana_hwc_get_msg_index() stores -EINPROGRESS as an in-band "no response yet"
state that mana_hwc_send_request() special-cases with
if (err != -EINPROGRESS). Should that sentinel be documented next to the
field, since every reader of ->error has to know about it?
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260908035201.402424-1-longli%40microsoft.com
next prev parent reply other threads:[~2026-09-11 6:53 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 3:51 [PATCH net-next v5 0/4] net: mana: concurrent HWC requests and dynamic queue depth Long Li
2026-09-08 3:51 ` [PATCH net-next v5 1/4] net: mana: track when the HWC has been handed to the PF Long Li
2026-09-09 3:52 ` sashiko-bot
2026-09-11 6:53 ` netdev-bot+sashiko
2026-09-08 3:51 ` [PATCH net-next v5 2/4] net: mana: give each HWC message slot its own completion state Long Li
2026-09-09 3:52 ` sashiko-bot
2026-09-11 6:53 ` netdev-bot+sashiko [this message]
2026-09-08 3:51 ` [PATCH net-next v5 3/4] net: mana: support concurrent HWC requests Long Li
2026-09-09 3:52 ` sashiko-bot
2026-09-11 6:53 ` netdev-bot+sashiko
2026-09-08 3:51 ` [PATCH net-next v5 4/4] net: mana: add dynamic HWC queue depth with reinit path Long Li
2026-09-09 3:52 ` sashiko-bot
2026-09-11 6:53 ` netdev-bot+sashiko
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=178910960289.219967.5929065773405833614@kernel.org \
--to=netdev-bot+sashiko@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=decui@microsoft.com \
--cc=edumazet@google.com \
--cc=ernis@linux.microsoft.com \
--cc=haiyangz@microsoft.com \
--cc=horms@kernel.org \
--cc=jgg@ziepe.ca \
--cc=kotaranov@microsoft.com \
--cc=kuba@kernel.org \
--cc=kys@microsoft.com \
--cc=leon@kernel.org \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=longli@kernel.org \
--cc=longli@microsoft.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=shirazsaleem@microsoft.com \
--cc=shradhagupta@linux.microsoft.com \
--cc=stephen@networkplumber.org \
--cc=wei.liu@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.