From: sashiko-bot@kernel.org
To: "Akhila Kavi" <akavi@axiado.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH net-next 2/2] net: mctp: Add Axiado AX3005 IRoT MCTP transport driver
Date: Mon, 02 Nov 2026 14:03:05 +0000 [thread overview]
Message-ID: <sashiko-outbox-193520@kernel.org> (raw)
In-Reply-To: <20261101-mctp-transport-irot-ax3005-v1-2-36ceb822f01e@axiado.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] net: mctp: irot_ndo_stop() cancelling tx_work wedges link after late TX ACK
- [High] net: mctp: unlocked netif_stop_queue() in irot_ndo_open() races with irot_tx_wake()
- [High] net: mctp: irot_rx_work() ACKs IROT_RX_INVALID without updating last_rx_counter
- [Medium] net: mctp: axiado: premature retry exhaustion in irot_discover_buffers()
--
commit c82310d54b9aff23038939986150dc23c6fe72a1
Author: Akhila Kavi <akavi@axiado.com>
net: mctp: Add Axiado AX3005 IRoT MCTP transport driver
This commit adds an MCTP transport driver for the IRoT co-processor on
Axiado AX3005 SoCs, carrying packets through shared-memory windows
negotiated and signaled over a mailbox interface.
> diff --git a/drivers/net/mctp/axiado-mctp-irot.c b/drivers/net/mctp/axiado-mctp-irot.c
> new file mode 100644
> index 0000000000000..d393a8102f2db
> --- /dev/null
> +++ b/drivers/net/mctp/axiado-mctp-irot.c
> @@ -0,0 +1,1089 @@
[ ... ]
> +/* cc_mctp_buffer: the peer's windows. Write-once; zero mtu means no answer. */
> +static void irot_cb_buffer_rsp(struct irot_priv *p, const struct irot_msg *m)
> +{
> + u32 mtu = le32_to_cpu(m->data.buffers.mtu_limit);
> +
> + scoped_guard(spinlock_irqsave, &p->rx_lock) {
> + if (!p->buffers_valid && mtu) {
> + irot_region_from_span(&p->host_write,
> + &m->data.buffers.host_write);
> + irot_region_from_span(&p->host_read,
> + &m->data.buffers.host_read);
> + p->mtu = mtu;
> + p->buffers_valid = true;
> + }
> + }
> +
> + complete(&p->buffers_done);
> +}
[Severity: Medium]
Should irot_cb_buffer_rsp() only call complete(&p->buffers_done) when mtu
is non-zero?
When the peer replies with IROT_CC_MCTP_BUFFER containing mtu_limit == 0,
p->buffers_valid remains false, but complete(&p->buffers_done) still wakes
wait_for_completion_timeout() in irot_discover_buffers() immediately:
for (i = 0; i < IROT_BUFFER_RETRIES && !got; i++) {
reinit_completion(&p->buffers_done);
rc = irot_send(p, &req);
...
wait_for_completion_timeout(&p->buffers_done,
secs_to_jiffies(IROT_BUFFER_TIMEOUT_S));
scoped_guard(spinlock_irqsave, &p->rx_lock)
got = p->buffers_valid;
}
Wouldn't this cause irot_discover_buffers() to spin through all
IROT_BUFFER_RETRIES attempts back-to-back without waiting for the intended
timeout window before failing probe with -ETIMEDOUT?
[ ... ]
> +static void irot_rx_work(struct work_struct *work)
> +{
[ ... ]
> + if (do_rx) {
> + res = irot_rx_deliver(p, &e, &dropped);
> +
> + scoped_guard(spinlock_irqsave, &p->rx_lock) {
> + p->rx_busy = false;
> + if (res == IROT_RX_DELIVERED) {
> + p->last_rx_counter = e.counter;
> + p->has_last_rx_counter = true;
> + }
> + }
> + }
> +
> + local_bh_disable();
> + if (dropped)
> + dev_dstats_rx_dropped_add(p->ndev, dropped);
> + if (do_rx && res == IROT_RX_DELIVERED)
> + dev_dstats_rx_add(p->ndev, e.size);
> + local_bh_enable();
> +
> + /* Withhold the ACK and the peer resends */
> + if (do_rx && res != IROT_RX_RETRY)
> + irot_send_done(p, e.counter);
> +}
[Severity: High]
When irot_rx_deliver() returns IROT_RX_INVALID (for example, when a packet
arrives while !netif_running(p->ndev)), irot_rx_work() still sends
IROT_CC_MCTP_DONE via irot_send_done(p, e.counter), which releases the
host_read window back to the IRoT.
However, p->rx_busy is cleared before irot_send_done() is called, and
p->last_rx_counter is only updated when res == IROT_RX_DELIVERED.
If the IRoT resends the same counter before receiving that ACK (or while
irot_send_done() is waiting on tx_chan_lock), irot_cb_mctp() will see
p->rx_busy == false and e.counter != p->last_rx_counter:
scoped_guard(spinlock_irqsave, &p->rx_lock) {
if (p->has_last_rx_counter && e.counter == p->last_rx_counter) {
/* Resend of a delivered packet: our ACK was missed */
p->dup_ack_counter = e.counter;
p->dup_ack_pending = true;
wake = true;
} else if (p->rx_busy) {
...
} else {
p->rx_entry = e;
p->rx_busy = true;
p->rx_new = true;
wake = true;
}
}
Can this cause the resend to be queued as a new packet in p->rx_entry,
allowing irot_rx_work() to read from host_read concurrently with the IRoT
writing the next packet after receiving the first IROT_CC_MCTP_DONE?
[ ... ]
> +static int irot_ndo_open(struct net_device *ndev)
> +{
> + struct irot_priv *p = netdev_priv(ndev);
> +
> + /*
> + * A busy or stalled window keeps the queue stopped; tx_work wakes it
> + * once the ACK arrives, since netif_running() is already true here.
> + */
> + if (irot_tx_ready(p))
> + netif_start_queue(ndev);
> + else
> + netif_stop_queue(ndev);
> +
> + return 0;
> +}
[Severity: High]
Can irot_ndo_open() race with irot_tx_wake() and leave the TX queue
permanently stopped?
In irot_ndo_open(), irot_tx_ready(p) checks !p->pending_write &&
!p->tx_stalled && !p->tx_skb under p->tx_state_lock, and then releases the
lock before calling netif_stop_queue(ndev).
If a packet was in flight from before the interface was closed and its
IROT_CC_MCTP_DONE arrives right after irot_tx_ready(p) returns false:
CPU0 CPU1
irot_ndo_open()
irot_tx_ready(p) -> false
irot_tx_mark_done()
p->pending_write = false;
queue_work(p->wq, &p->tx_work);
irot_tx_work()
irot_tx_wake()
lock(&p->tx_state_lock)
netif_wake_queue(p->ndev);
unlock(&p->tx_state_lock)
netif_stop_queue(ndev);
Since p->pending_write is now false and no further ACK will arrive,
wouldn't netif_stop_queue(ndev) leave the queue stopped forever?
> +
> +static int irot_ndo_stop(struct net_device *ndev)
> +{
> + struct irot_priv *p = netdev_priv(ndev);
> + struct sk_buff *skb;
> +
> + netif_stop_queue(ndev);
> +
> + /*
> + * Do not touch tx_timeout_work: a packet in flight still owns the
> + * window, and the stall and late-ACK handling must keep running.
> + */
> + cancel_work_sync(&p->tx_work);
[Severity: High]
What happens if a stalled TX transfer receives its late IROT_CC_MCTP_DONE
just before irot_ndo_stop() runs cancel_work_sync(&p->tx_work)?
When a TX transfer times out, irot_tx_stall() sets p->tx_stalled = true and
calls netif_carrier_off(p->ndev). When the late ACK arrives in
irot_rx_callback(), irot_tx_mark_done() clears p->pending_write and queues
p->tx_work:
scoped_guard(spinlock_irqsave, &p->tx_state_lock) {
if (!p->pending_write || p->pending_tx_counter != counter)
return;
p->pending_write = false;
}
cancel_delayed_work(&p->tx_timeout_work);
queue_work(p->wq, &p->tx_work);
Clearing p->tx_stalled and calling netif_carrier_on(p->ndev) only happens
when p->tx_work runs irot_tx_wake():
scoped_guard(spinlock_irqsave, &p->tx_state_lock) {
if (p->pending_write || p->tx_skb)
return;
if (p->tx_stalled) {
p->tx_stalled = false;
recovered = true;
}
...
}
if (recovered) {
dev_dbg(p->dev, "late TX ACK arrived, link up\n");
netif_carrier_on(p->ndev);
}
If irot_ndo_stop() cancels p->tx_work after irot_tx_mark_done() has already
set p->pending_write = false, irot_tx_wake() never runs. Does this leave
p->tx_stalled == true and the carrier off permanently, causing subsequent
irot_ndo_open() calls to see irot_tx_ready(p) == false and keep the TX
queue stopped?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261101-mctp-transport-irot-ax3005-v1-0-36ceb822f01e@axiado.com?part=2
next prev parent reply other threads:[~2026-11-02 14:03 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-01 14:00 [PATCH net-next 0/2] net: mctp: Add MCTP transport for the Axiado AX3005 IRoT Akhila Kavi
2026-11-01 14:00 ` [PATCH net-next 1/2] dt-bindings: net: Add Axiado AX3005 IRoT MCTP transport Akhila Kavi
2026-11-02 11:40 ` Krzysztof Kozlowski
2026-11-01 14:00 ` [PATCH net-next 2/2] net: mctp: Add Axiado AX3005 IRoT MCTP transport driver Akhila Kavi
2026-11-02 14:03 ` sashiko-bot [this message]
2026-11-02 2:55 ` [PATCH net-next 0/2] net: mctp: Add MCTP transport for the Axiado AX3005 IRoT Jeremy Kerr
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=sashiko-outbox-193520@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=akavi@axiado.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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