[PATCH 05/11] NTB: ntb_transport: Avoid deadlock when cancelling link work
From: Koichiro Den
Date: Mon Sep 07 2026 - 10:36:21 EST
During initial link setup, ntb_transport_link_work() can retry with
nt->link_is_up still false. A retry can block on link_event_lock
while cleanup holds it and waits in cancel_delayed_work_sync(),
leading to deadlock.
Move the conditional cancellation outside link_event_lock, before
QP cleanup. Keep QP cleanup and MW release under the lock so link
work cannot restart QPs between them. Put the locking in
ntb_transport_link_cleanup() to cover both worker and remove paths.
Fixes: 3db835dd8f9a ("ntb: Add mutex to make link_event_callback executed linearly.")
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
drivers/ntb/ntb_transport.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 763e4bb175a3..c8e7fc774b4f 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -973,6 +973,15 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
struct ntb_transport_qp *qp;
u64 qp_bitmap_alloc;
unsigned int i, count;
+ bool cancel_link_work;
+
+ scoped_guard(mutex, &nt->link_event_lock)
+ cancel_link_work = !nt->link_is_up;
+
+ if (cancel_link_work)
+ cancel_delayed_work_sync(&nt->link_work);
+
+ guard(mutex)(&nt->link_event_lock);
qp_bitmap_alloc = nt->qp_bitmap & ~nt->qp_bitmap_free;
@@ -985,9 +994,6 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
cancel_delayed_work_sync(&qp->link_work);
}
- if (!nt->link_is_up)
- cancel_delayed_work_sync(&nt->link_work);
-
for (i = 0; i < nt->mw_count; i++)
ntb_free_mw(nt, i);
@@ -1005,7 +1011,6 @@ static void ntb_transport_link_cleanup_work(struct work_struct *work)
struct ntb_transport_ctx *nt =
container_of(work, struct ntb_transport_ctx, link_cleanup);
- guard(mutex)(&nt->link_event_lock);
ntb_transport_link_cleanup(nt);
}
--
2.51.0