Thread (17 messages) 17 messages, 2 authors, 4d ago

Re: [PATCH v20 net-next 04/10] net/nebula-matrix: add channel layer

From: Paolo Abeni <pabeni@redhat.com>
Date: 2026-07-02 09:42:51
Also in: linux-doc, lkml

From: AI Reviewer <redacted>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev/
---
Subject: net/nebula-matrix: add channel layer

This patch introduces a channel management layer for structured communication
between components and drivers. It implements message registration, sending,
and acknowledgment via hardware mailbox queues.
quoted hunk ↗ jump to hunk
diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.c b/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.c
index c7689f0e40293..eca9495449938 100644
--- a/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.c
+++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_channel/nbl_channel.c
[ ... ]
quoted hunk ↗ jump to hunk
@@ -2,12 +2,997 @@
[ ... ]
+static int nbl_chan_teardown_queue(struct nbl_channel_mgt *chan_mgt,
+				   u8 chan_type)
+{
[ ... ]
+	/*
+	 * Lock and unlock to ensure all in-flight callers have released the
+	 * lock. After unlock returns, we're guaranteed no other thread is
+	 * using the lock, so it's safe to destroy it.
+	 */
+	mutex_lock(&chan_info->txq_lock);
+	mutex_unlock(&chan_info->txq_lock);
+	wait_for_completion(&chan_info->teardown_done);
+	mutex_destroy(&chan_info->txq_lock);
+
+	return 0;
+}
[Severity: High]
Does this code deadlock or fail to synchronize?

Because nbl_chan_send_msg() calls complete(&chan_info->teardown_done) on
every exit path, it increments the completion counter for every message sent.
If no messages were ever sent, the counter is 0 and this wait_for_completion()
will block forever.

If messages were sent, the counter is greater than 0, so this returns
immediately without waiting for active senders. It then destroys txq_lock
while other threads might still be using it, which can cause a use-after-free
or lock corruption.

[ ... ]
+static int nbl_chan_update_txqueue(struct nbl_channel_mgt *chan_mgt,
+				   struct nbl_chan_info *chan_info,
+				   struct nbl_chan_tx_param *param)
+{
[ ... ]
+	if (param->arg_len > NBL_CHAN_TX_DESC_EMBEDDED_DATA_LEN) {
+		memcpy(tx_buf->va, param->arg, param->arg_len);
+		tx_desc->buf_addr = cpu_to_le64(tx_buf->pa);
+		tx_desc->buf_len = cpu_to_le16(param->arg_len);
+		tx_desc->data_len = 0;
+		memset(tx_desc->data, 0, sizeof(tx_desc->data));
+	} else {
+		memset(tx_desc->data, 0, sizeof(tx_desc->data));
+		memcpy(tx_desc->data, param->arg, param->arg_len);
+		tx_desc->buf_len = 0;
+		tx_desc->data_len = cpu_to_le16(param->arg_len);
+	}
[Severity: High]
Does this code leak host physical memory addresses to the receiving endpoint?

In the else branch (when embedding data), tx_desc->buf_addr is not cleared.
Since the TX descriptor ring is reused circularly, if this slot previously held
a large message, buf_addr still contains the physical DMA address of the host's
buffer.

This leaked physical address is written to memory shared with the receiving
endpoint, potentially crossing a security boundary.

[ ... ]
+static void nbl_chan_clean_queue(struct nbl_channel_mgt *chan_mgt,
+				 struct nbl_chan_info *chan_info)
+{
[ ... ]
+	while (le16_to_cpu(rx_desc->flags) & BIT(NBL_CHAN_RX_DESC_USED)) {
[ ... ]
+		if (--budget == 0)
+			break;
+	}
+	rxq->next_to_clean = next_to_clean;
+}
[Severity: High]
Can this permanently stall the RX queue?

The loop exits when the budget is exhausted, but nbl_chan_clean_queue()
returns void and doesn't indicate that more packets remain.

The workqueue handler does not check if the RX queue was completely drained
and won't reschedule the work item. If the ring wasn't completely drained,
edge-triggered MSI-X interrupts won't fire again until a new packet arrives,
leading to a stalled queue and missed messages.

[ ... ]
+static int nbl_chan_send_msg(struct nbl_channel_mgt *chan_mgt,
+			     struct nbl_chan_send_info *chan_send)
+{
[ ... ]
+	if (!chan_send->ack) {
+		complete(&chan_info->teardown_done);
+		return 0;
+	}
[Severity: High]
Is it intentional to call complete(&chan_info->teardown_done) here and on
all other exit paths of nbl_chan_send_msg()?

This increments the completion counter on every message sent, which breaks the
synchronization in nbl_chan_teardown_queue() (as mentioned above).

[ ... ]
-- 
This is an AI-generated review.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help