[PATCH v2 10/14] NTB: ntb_transport: Wait for RX completions before resetting a QP

From: Koichiro Den

Date: Thu Sep 10 2026 - 00:12:44 EST


Transport link cleanup can free an MW still used by RX DMA or its
completion path. QP-only cleanup retains the MW, but can restart RX
on ring slots whose old completion callbacks have not yet cleared
the headers.

Wait for rx_post_q to empty before resetting the QP. ntb_complete_rxc()
finishes its MW accesses before removing each entry under ntb_rx_q_lock,
so cleanup can free the MW without racing with these RX accesses.
Using dmaengine_terminate_sync() instead would not work with drivers
such as IOAT that lack the required ops. Cookie-based waits would
not work with DMA_COMPLETION_NO_ORDER either.

DMA teardown in ntb_transport_free_queue() is unchanged.

Fixes: 9143595a7e05 ("NTB: ntb_transport: Free MWs in ntb_transport_link_cleanup()")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Link: https://lore.kernel.org/r/20260907144257.767281F00A3A@xxxxxxxxxxxxxxx/
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
Changes in v2:
- New patch (Sashiko).

drivers/ntb/ntb_transport.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 36797ea3ff45..7ccba2c04f54 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -949,6 +949,13 @@ static void ntb_transport_schedule_qp_link(struct ntb_transport_qp *qp,
schedule_delayed_work(&qp->link_work, delay);
}

+static bool ntb_transport_rx_idle(struct ntb_transport_qp *qp)
+{
+ guard(spinlock_irqsave)(&qp->ntb_rx_q_lock);
+
+ return list_empty(&qp->rx_post_q);
+}
+
static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
{
struct ntb_transport_ctx *nt = qp->transport;
@@ -959,6 +966,17 @@ static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
disable_delayed_work_sync(&qp->link_work);
ntb_transport_set_qp_active(qp, false);
tasklet_kill(&qp->rxc_db_work);
+ /*
+ * Some DMA engines lack terminate/synchronize ops (e.g. IOAT), and
+ * DMA_COMPLETION_NO_ORDER rules out cookie-based waits.
+ *
+ * Waiting for rx_post_q to empty suffices: ntb_complete_rxc() finishes
+ * its MW accesses before removing each entry under ntb_rx_q_lock.
+ * qp->active is false and rxc_db_work is stopped, so no new RX DMA
+ * can be submitted.
+ */
+ while (!ntb_transport_rx_idle(qp))
+ fsleep(1000);

ntb_qp_link_down_reset(qp);

--
2.51.0