Re: [PATCH v2 10/14] NTB: ntb_transport: Wait for RX completions before resetting a QP
From: Dave Jiang
Date: Thu Sep 24 2026 - 12:00:22 EST
On 9/9/26 9:08 PM, Koichiro Den wrote:
> 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>
Reviewed-by: Dave Jiang <dave.jiang@xxxxxxxxx>
> ---
> 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);
>