* [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes
@ 2026-09-28 15:25 Koichiro Den
2026-09-28 15:25 ` [PATCH v3 01/15] NTB: ntb_transport: Remove the device debugfs directory Koichiro Den
` (14 more replies)
0 siblings, 15 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
Hi,
This series attempts to fix miscellaneous issues in ntb_transport. Some
of these were split from the direct TX/RX series v1 [1], as they stand
on their own. Based on v7.3-rc2.
Dave, Frank and Logan, for v3, patches 3 and 6 don't yet have
Reviewed-by tags. Could you take a look?
Best regards,
Koichiro
[1] https://lore.kernel.org/r/20260810165136.2292436-1-den@valinux.co.jp/
---
Changes in v3:
- Convert flags to atomic_t in a new prep patch. (Frank)
- Drop the redundant TX credit assertion. (Sashiko)
- Collect Reviewed-by tags. Thanks to Frank, Logan and Dave.
Changes in v2:
- Address Sashiko feedback, including regressions introduced by v1,
with new patches 5 and 10.
Note that to keep the series manageable, this revision does not
attempt to fix all the reported pre-existing issues.
- Add a fix for client removal ordering (patch 14).
- Reorder patches, moving v1 patch 4 after the fixes it depends on.
- Add missing Cc: stable@vger.kernel.org.
v2: https://lore.kernel.org/r/20260910040836.3792333-1-den@valinux.co.jp/
v1: https://lore.kernel.org/r/20260907142429.951930-1-den@valinux.co.jp/
Koichiro Den (15):
NTB: ntb_transport: Remove the device debugfs directory
NTB: ntb_transport: Start TX offload thread after queue setup
NTB: ntb_transport: Make link setup flags atomic
NTB: ntb_transport: Avoid deadlock when cancelling link work
NTB: ntb_transport: Publish link state after QP setup
NTB: ntb_transport: Avoid losing QP link-up requests
NTB: ntb_transport: Clear link state before QP cleanup
NTB: ntb_transport: Stop QP work before freeing a queue
NTB: ntb_transport: Stop RX tasklet scheduling before freeing a queue
NTB: ntb_transport: Drain RX tasklets during link cleanup
NTB: ntb_transport: Wait for RX completions before resetting a QP
NTB: ntb_transport: Prepare remote RX info accesses for MW teardown
NTB: ntb_transport: Clear QP pointers when freeing an MW
NTB: ntb_transport: Abort link setup on QP MW allocation failure
NTB: ntb_transport: Remove clients before freeing transport resources
drivers/ntb/ntb_transport.c | 244 ++++++++++++++++++++++++------------
1 file changed, 167 insertions(+), 77 deletions(-)
base-commit: df2908090cda368b01ff43709f51890076c56157
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 01/15] NTB: ntb_transport: Remove the device debugfs directory
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 02/15] NTB: ntb_transport: Start TX offload thread after queue setup Koichiro Den
` (13 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
ntb_transport_free() removes QP debugfs directories but leaves the
device directory. On rebind, debugfs_create_dir() fails with -EEXIST
and QP statistics files are not recreated. Module unload masks this
by removing the entire debugfs tree.
To reproduce:
# ls /sys/kernel/debug/ntb_transport/0001:10:00.0/
qp0
# echo 0001:10:00.0 > /sys/bus/ntb/drivers/ntb_transport/unbind
# ls /sys/kernel/debug/ntb_transport/
0001:10:00.0 <-- should not remain
# echo 0001:10:00.0 > /sys/bus/ntb/drivers/ntb_transport/bind
.. and then dmesg shows:
debugfs: '0001:10:00.0' already exists in 'ntb_transport'
# ls /sys/kernel/debug/ntb_transport/0001:10:00.0/
(nothing) <-- should be 'qp0'
Remove the device debugfs tree on teardown and probe failure.
Verified that unbind removes the directory and rebind recreates qp0.
Fixes: c8650fd03d32 ("NTB: Fix transport stats for multiple devices")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Add Reviewed-by tags. No code changes.
drivers/ntb/ntb_transport.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index f9caa1a653c5..3389d6ca9ebd 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -1382,6 +1382,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
err3:
ntb_clear_ctx(ndev);
err2:
+ debugfs_remove_recursive(nt->debugfs_node_dir);
kfree(nt->qp_vec);
err1:
while (i--) {
@@ -1401,6 +1402,8 @@ static void ntb_transport_free(struct ntb_client *self, struct ntb_dev *ndev)
u64 qp_bitmap_alloc;
int i;
+ debugfs_remove_recursive(nt->debugfs_node_dir);
+
ntb_transport_link_cleanup(nt);
cancel_work_sync(&nt->link_cleanup);
cancel_delayed_work_sync(&nt->link_work);
@@ -1412,7 +1415,6 @@ static void ntb_transport_free(struct ntb_client *self, struct ntb_dev *ndev)
qp = &nt->qp_vec[i];
if (qp_bitmap_alloc & BIT_ULL(i))
ntb_transport_free_queue(qp);
- debugfs_remove_recursive(qp->debugfs_dir);
}
ntb_link_disable(ndev);
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 02/15] NTB: ntb_transport: Start TX offload thread after queue setup
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
2026-09-28 15:25 ` [PATCH v3 01/15] NTB: ntb_transport: Remove the device debugfs directory Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 03/15] NTB: ntb_transport: Make link setup flags atomic Koichiro Den
` (12 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
ntb_transport_create_queue() starts the per-QP TX offload thread before
DMA mappings and queue entries are allocated. If later setup fails, the
error path returns the QP to the free bitmap without stopping the
thread. A retry can then reinitialize its waitqueue while the old thread
is still waiting on it.
Start the thread after queue setup.
Fixes: 322617a06c97 ("NTB: ntb_transport: Add 'tx_memcpy_offload' module option")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Add Reviewed-by tags. No code changes.
drivers/ntb/ntb_transport.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 3389d6ca9ebd..55a20ae9a85e 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -2055,20 +2055,6 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
qp->tx_handler = handlers->tx_handler;
qp->event_handler = handlers->event_handler;
- init_waitqueue_head(&qp->tx_offload_wq);
- if (tx_memcpy_offload) {
- qp->tx_offload_thread = kthread_run(ntb_tx_memcpy_kthread, qp,
- "ntb-txcpy/%s/%u",
- pci_name(ndev->pdev), qp->qp_num);
- if (IS_ERR(qp->tx_offload_thread)) {
- dev_warn(&nt->ndev->dev,
- "tx memcpy offload thread creation failed: %ld; falling back to inline copy\n",
- PTR_ERR(qp->tx_offload_thread));
- qp->tx_offload_thread = NULL;
- }
- } else
- qp->tx_offload_thread = NULL;
-
dma_cap_zero(dma_mask);
dma_cap_set(DMA_MEMCPY, dma_mask);
@@ -2129,6 +2115,20 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
&qp->tx_free_q);
}
+ init_waitqueue_head(&qp->tx_offload_wq);
+ qp->tx_offload_thread = NULL;
+ if (tx_memcpy_offload) {
+ qp->tx_offload_thread = kthread_run(ntb_tx_memcpy_kthread, qp,
+ "ntb-txcpy/%s/%u",
+ pci_name(ndev->pdev), qp->qp_num);
+ if (IS_ERR(qp->tx_offload_thread)) {
+ dev_warn(&nt->ndev->dev,
+ "tx memcpy offload thread creation failed: %ld; falling back to inline copy\n",
+ PTR_ERR(qp->tx_offload_thread));
+ qp->tx_offload_thread = NULL;
+ }
+ }
+
ntb_db_clear(qp->ndev, qp_bit);
ntb_db_clear_mask(qp->ndev, qp_bit);
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 03/15] NTB: ntb_transport: Make link setup flags atomic
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
2026-09-28 15:25 ` [PATCH v3 01/15] NTB: ntb_transport: Remove the device debugfs directory Koichiro Den
2026-09-28 15:25 ` [PATCH v3 02/15] NTB: ntb_transport: Start TX offload thread after queue setup Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:53 ` Logan Gunthorpe
2026-09-28 15:25 ` [PATCH v3 04/15] NTB: ntb_transport: Avoid deadlock when cancelling link work Koichiro Den
` (11 subsequent siblings)
14 siblings, 1 reply; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
Convert nt->link_is_up and qp->client_ready to atomic_t and use atomic
accessors throughout. This prepares for the unlocked cleanup check and
the link-up ordering fixes that follow.
Leave control flow and locking unchanged.
Cc: stable@vger.kernel.org
Suggested-by: Frank Li <Frank.Li@kernel.org>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- New patch. (Frank)
https://lore.kernel.org/r/i3b4kyeuwyjssav2kne5uhxmltwl2bmug2weyfaujxtrwlkuox@ms6ozb55tmz5/
drivers/ntb/ntb_transport.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 55a20ae9a85e..5d2ec484c3df 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -47,6 +47,7 @@
* Contact Information:
* Jon Mason <jon.mason@intel.com>
*/
+#include <linux/atomic.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
@@ -142,7 +143,7 @@ struct ntb_transport_qp {
struct dma_chan *tx_dma_chan;
struct dma_chan *rx_dma_chan;
- bool client_ready;
+ atomic_t client_ready;
bool link_is_up;
bool active;
@@ -249,7 +250,7 @@ struct ntb_transport_ctx {
unsigned int msi_spad_offset;
u64 msi_db_mask;
- bool link_is_up;
+ atomic_t link_is_up;
struct delayed_work link_work;
struct work_struct link_cleanup;
@@ -945,7 +946,7 @@ static void ntb_qp_link_cleanup_work(struct work_struct *work)
ntb_qp_link_cleanup(qp);
- if (nt->link_is_up)
+ if (atomic_read(&nt->link_is_up))
schedule_delayed_work(&qp->link_work,
msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
}
@@ -972,7 +973,7 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
cancel_delayed_work_sync(&qp->link_work);
}
- if (!nt->link_is_up)
+ if (!atomic_read(&nt->link_is_up))
cancel_delayed_work_sync(&nt->link_work);
for (i = 0; i < nt->mw_count; i++)
@@ -1084,7 +1085,7 @@ static void ntb_transport_link_work(struct work_struct *work)
goto out1;
}
- nt->link_is_up = true;
+ atomic_set(&nt->link_is_up, true);
for (i = 0; i < nt->qp_count; i++) {
struct ntb_transport_qp *qp = &nt->qp_vec[i];
@@ -1092,7 +1093,7 @@ static void ntb_transport_link_work(struct work_struct *work)
ntb_transport_setup_qp_mw(nt, i);
ntb_transport_setup_qp_peer_msi(nt, i);
- if (qp->client_ready)
+ if (atomic_read(&qp->client_ready))
schedule_delayed_work(&qp->link_work, 0);
}
@@ -1121,7 +1122,7 @@ static void ntb_qp_link_work(struct work_struct *work)
struct ntb_transport_ctx *nt = qp->transport;
int val;
- WARN_ON(!nt->link_is_up);
+ WARN_ON(!atomic_read(&nt->link_is_up));
val = ntb_spad_read(nt->ndev, QP_LINKS);
@@ -1141,7 +1142,7 @@ static void ntb_qp_link_work(struct work_struct *work)
if (qp->active)
tasklet_schedule(&qp->rxc_db_work);
- } else if (nt->link_is_up)
+ } else if (atomic_read(&nt->link_is_up))
schedule_delayed_work(&qp->link_work,
msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
}
@@ -1165,7 +1166,7 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
qp->qp_num = qp_num;
qp->transport = nt;
qp->ndev = nt->ndev;
- qp->client_ready = false;
+ atomic_set(&qp->client_ready, false);
qp->event_handler = NULL;
ntb_qp_link_context_reset(qp);
@@ -1373,7 +1374,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
if (rc)
goto err3;
- nt->link_is_up = false;
+ atomic_set(&nt->link_is_up, false);
ntb_link_enable(ndev, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
ntb_link_event(ndev);
@@ -1457,7 +1458,7 @@ static void ntb_complete_rxc(struct ntb_transport_qp *qp)
spin_unlock_irqrestore(&qp->ntb_rx_q_lock, irqflags);
- if (qp->rx_handler && qp->client_ready)
+ if (qp->rx_handler && atomic_read(&qp->client_ready))
qp->rx_handler(qp, qp->cb_data, cb_data, len);
spin_lock_irqsave(&qp->ntb_rx_q_lock, irqflags);
@@ -2268,7 +2269,7 @@ void *ntb_transport_rx_remove(struct ntb_transport_qp *qp, unsigned int *len)
struct ntb_queue_entry *entry;
void *buf;
- if (!qp || qp->client_ready)
+ if (!qp || atomic_read(&qp->client_ready))
return NULL;
entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_pend_q);
@@ -2385,9 +2386,9 @@ void ntb_transport_link_up(struct ntb_transport_qp *qp)
if (!qp)
return;
- qp->client_ready = true;
+ atomic_set(&qp->client_ready, true);
- if (qp->transport->link_is_up)
+ if (atomic_read(&qp->transport->link_is_up))
schedule_delayed_work(&qp->link_work, 0);
}
EXPORT_SYMBOL_GPL(ntb_transport_link_up);
@@ -2407,7 +2408,7 @@ void ntb_transport_link_down(struct ntb_transport_qp *qp)
if (!qp)
return;
- qp->client_ready = false;
+ atomic_set(&qp->client_ready, false);
val = ntb_spad_read(qp->ndev, QP_LINKS);
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 04/15] NTB: ntb_transport: Avoid deadlock when cancelling link work
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (2 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 03/15] NTB: ntb_transport: Make link setup flags atomic Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 05/15] NTB: ntb_transport: Publish link state after QP setup Koichiro Den
` (10 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
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.")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Use atomic_read() for the cancellation check instead of taking
link_event_lock.
- Carry over Reviewed-by.
v2: https://lore.kernel.org/r/20260910040836.3792333-4-den@valinux.co.jp/
@Logan, with link_is_up now atomic_t, I dropped the mutex acquisition
around the cancellation check. Would appreciate another look, thanks.
drivers/ntb/ntb_transport.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 5d2ec484c3df..8941da0b3d61 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -962,6 +962,11 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
u64 qp_bitmap_alloc;
unsigned int i, count;
+ if (!atomic_read(&nt->link_is_up))
+ cancel_delayed_work_sync(&nt->link_work);
+
+ guard(mutex)(&nt->link_event_lock);
+
qp_bitmap_alloc = nt->qp_bitmap & ~nt->qp_bitmap_free;
/* Pass along the info to any clients */
@@ -973,9 +978,6 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
cancel_delayed_work_sync(&qp->link_work);
}
- if (!atomic_read(&nt->link_is_up))
- cancel_delayed_work_sync(&nt->link_work);
-
for (i = 0; i < nt->mw_count; i++)
ntb_free_mw(nt, i);
@@ -993,7 +995,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
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 05/15] NTB: ntb_transport: Publish link state after QP setup
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (3 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 04/15] NTB: ntb_transport: Avoid deadlock when cancelling link work Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 06/15] NTB: ntb_transport: Avoid losing QP link-up requests Koichiro Den
` (9 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
ntb_transport_link_work() marks the transport link up before setting
up the QPs' MW and peer MSI state. A concurrent ntb_transport_link_up()
can then queue QP link work, which may enable RX and notify the client
before setup finishes.
Publish link_is_up with a release store after setting up all QPs,
and use acquire loads before queuing QP link work.
Fixes: fce8a7bb5b4b ("PCI-Express Non-Transparent Bridge Support")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/anyKbq3mpLG4y7rb@SMW015318
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Use atomic release/acquire accessors.
- Carry over Reviewed-by tags.
v2: https://lore.kernel.org/r/20260910040836.3792333-5-den@valinux.co.jp/
drivers/ntb/ntb_transport.c | 40 +++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 15 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 8941da0b3d61..51d9e9969065 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -923,6 +923,16 @@ static void ntb_qp_link_down_reset(struct ntb_transport_qp *qp)
qp->remote_rx_info->entry = qp->rx_max_entry - 1;
}
+static void ntb_transport_schedule_qp_link(struct ntb_transport_qp *qp,
+ unsigned long delay)
+{
+ struct ntb_transport_ctx *nt = qp->transport;
+
+ /* Pair with the link publication in ntb_transport_link_work(). */
+ if (atomic_read_acquire(&nt->link_is_up))
+ schedule_delayed_work(&qp->link_work, delay);
+}
+
static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
{
struct ntb_transport_ctx *nt = qp->transport;
@@ -942,13 +952,10 @@ static void ntb_qp_link_cleanup_work(struct work_struct *work)
struct ntb_transport_qp *qp = container_of(work,
struct ntb_transport_qp,
link_cleanup);
- struct ntb_transport_ctx *nt = qp->transport;
ntb_qp_link_cleanup(qp);
-
- if (atomic_read(&nt->link_is_up))
- schedule_delayed_work(&qp->link_work,
- msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
+ ntb_transport_schedule_qp_link(qp,
+ msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
}
static void ntb_qp_link_down(struct ntb_transport_qp *qp)
@@ -1086,16 +1093,19 @@ static void ntb_transport_link_work(struct work_struct *work)
goto out1;
}
- atomic_set(&nt->link_is_up, true);
-
for (i = 0; i < nt->qp_count; i++) {
- struct ntb_transport_qp *qp = &nt->qp_vec[i];
-
ntb_transport_setup_qp_mw(nt, i);
ntb_transport_setup_qp_peer_msi(nt, i);
+ }
+
+ /* Publish the link only after every QP has been set up. */
+ atomic_set_release(&nt->link_is_up, true);
+
+ for (i = 0; i < nt->qp_count; i++) {
+ struct ntb_transport_qp *qp = &nt->qp_vec[i];
if (atomic_read(&qp->client_ready))
- schedule_delayed_work(&qp->link_work, 0);
+ ntb_transport_schedule_qp_link(qp, 0);
}
return;
@@ -1143,9 +1153,10 @@ static void ntb_qp_link_work(struct work_struct *work)
if (qp->active)
tasklet_schedule(&qp->rxc_db_work);
- } else if (atomic_read(&nt->link_is_up))
- schedule_delayed_work(&qp->link_work,
- msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
+ } else {
+ ntb_transport_schedule_qp_link(qp,
+ msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
+ }
}
static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
@@ -2389,8 +2400,7 @@ void ntb_transport_link_up(struct ntb_transport_qp *qp)
atomic_set(&qp->client_ready, true);
- if (atomic_read(&qp->transport->link_is_up))
- schedule_delayed_work(&qp->link_work, 0);
+ ntb_transport_schedule_qp_link(qp, 0);
}
EXPORT_SYMBOL_GPL(ntb_transport_link_up);
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 06/15] NTB: ntb_transport: Avoid losing QP link-up requests
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (4 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 05/15] NTB: ntb_transport: Publish link state after QP setup Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 16:57 ` Logan Gunthorpe
2026-09-28 15:25 ` [PATCH v3 07/15] NTB: ntb_transport: Clear link state before QP cleanup Koichiro Den
` (8 subsequent siblings)
14 siblings, 1 reply; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
ntb_netdev_open() can call ntb_transport_link_up() while the transport
worker is completing setup on another CPU. Concurrent transport setup
and a client link-up request can both read the other's flag as false and
leave QP link work unqueued. The QP then stays down until another link
event or client link-up request.
This is the store-buffering pattern described in
tools/memory-model/Documentation/recipes.txt ("Store buffering").
Add a full barrier between the store and load on each side.
Fixes: fce8a7bb5b4b ("PCI-Express Non-Transparent Bridge Support")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/r/20260907144701.702E41F00A3A@smtp.kernel.org/
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Drop the *_ONCE changes. client_ready is now atomic_t.
v2: https://lore.kernel.org/r/20260910040836.3792333-6-den@valinux.co.jp/
drivers/ntb/ntb_transport.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 51d9e9969065..d290e5869c21 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -1101,6 +1101,12 @@ static void ntb_transport_link_work(struct work_struct *work)
/* Publish the link only after every QP has been set up. */
atomic_set_release(&nt->link_is_up, true);
+ /*
+ * Prevent both sides from missing each other's flag. Pairs with
+ * the barrier in ntb_transport_link_up().
+ */
+ smp_mb();
+
for (i = 0; i < nt->qp_count; i++) {
struct ntb_transport_qp *qp = &nt->qp_vec[i];
@@ -2400,6 +2406,9 @@ void ntb_transport_link_up(struct ntb_transport_qp *qp)
atomic_set(&qp->client_ready, true);
+ /* Pairs with the barrier in ntb_transport_link_work(). */
+ smp_mb();
+
ntb_transport_schedule_qp_link(qp, 0);
}
EXPORT_SYMBOL_GPL(ntb_transport_link_up);
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 07/15] NTB: ntb_transport: Clear link state before QP cleanup
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (5 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 06/15] NTB: ntb_transport: Avoid losing QP link-up requests Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 08/15] NTB: ntb_transport: Stop QP work before freeing a queue Koichiro Den
` (7 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
Cleanup leaves the transport link marked up after releasing its MWs.
A subsequent client link-up request can therefore start QP link work
before the transport has been set up again.
Clear link_is_up before cancelling QP work and releasing the MWs.
Have QP link work return if the transport went down after it was
queued.
Fixes: e26a5843f7f5 ("NTB: Split ntb_hw_intel and ntb_transport drivers")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Use atomic accessors for link_is_up. (Frank)
- Carry over Reviewed-by.
v2: https://lore.kernel.org/r/20260910040836.3792333-7-den@valinux.co.jp/
drivers/ntb/ntb_transport.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index d290e5869c21..571d633c4f0b 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -974,6 +974,8 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
guard(mutex)(&nt->link_event_lock);
+ atomic_set(&nt->link_is_up, false);
+
qp_bitmap_alloc = nt->qp_bitmap & ~nt->qp_bitmap_free;
/* Pass along the info to any clients */
@@ -1139,7 +1141,9 @@ static void ntb_qp_link_work(struct work_struct *work)
struct ntb_transport_ctx *nt = qp->transport;
int val;
- WARN_ON(!atomic_read(&nt->link_is_up));
+ /* Pair with the link publication in ntb_transport_link_work(). */
+ if (!atomic_read_acquire(&nt->link_is_up))
+ return;
val = ntb_spad_read(nt->ndev, QP_LINKS);
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 08/15] NTB: ntb_transport: Stop QP work before freeing a queue
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (6 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 07/15] NTB: ntb_transport: Clear link state before QP cleanup Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 09/15] NTB: ntb_transport: Stop RX tasklet scheduling " Koichiro Den
` (6 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
ntb_transport_free_queue() cancels qp->link_work but not qp->link_cleanup.
A peer link-down message can queue cleanup while ntb_netdev is freeing
the QP. Cleanup can then requeue link work after the queue resources
have been freed.
Disable and wait for cleanup, then link work, before freeing resources.
Unlike cancel, disable also prevents the RX tasklet and transport link
setup from queuing more work. Enable the works only after queue creation
succeeds.
Clear client_ready first so RX completions and transport link setup see
that the client is no longer ready. Clear link_is_up and active after
the workers stop, since link work can set both back to true.
Fixes: 7b4f2d3c3b82 ("NTB: No sleeping in interrupt context")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Clear client_ready with atomic_set().
- Carry over Reviewed-by.
v2: https://lore.kernel.org/r/20260910040836.3792333-8-den@valinux.co.jp/
drivers/ntb/ntb_transport.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 571d633c4f0b..556e1d255284 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -1239,6 +1239,8 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
INIT_DELAYED_WORK(&qp->link_work, ntb_qp_link_work);
INIT_WORK(&qp->link_cleanup, ntb_qp_link_cleanup_work);
+ disable_delayed_work(&qp->link_work);
+ disable_work(&qp->link_cleanup);
spin_lock_init(&qp->ntb_rx_q_lock);
spin_lock_init(&qp->ntb_tx_free_q_lock);
@@ -2152,6 +2154,9 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
}
}
+ enable_work(&qp->link_cleanup);
+ enable_delayed_work(&qp->link_work);
+
ntb_db_clear(qp->ndev, qp_bit);
ntb_db_clear_mask(qp->ndev, qp_bit);
@@ -2197,6 +2202,10 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
pdev = qp->ndev->pdev;
+ atomic_set(&qp->client_ready, false);
+ disable_work_sync(&qp->link_cleanup);
+ disable_delayed_work_sync(&qp->link_work);
+ qp->link_is_up = false;
qp->active = false;
if (qp->tx_offload_thread) {
@@ -2244,8 +2253,6 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
ntb_db_set_mask(qp->ndev, qp_bit);
tasklet_kill(&qp->rxc_db_work);
- cancel_delayed_work_sync(&qp->link_work);
-
qp->cb_data = NULL;
qp->rx_handler = NULL;
qp->tx_handler = NULL;
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 09/15] NTB: ntb_transport: Stop RX tasklet scheduling before freeing a queue
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (7 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 08/15] NTB: ntb_transport: Stop QP work before freeing a queue Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 10/15] NTB: ntb_transport: Drain RX tasklets during link cleanup Koichiro Den
` (5 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
A caller can read qp->active before teardown clears it, then schedule
the RX tasklet after tasklet_kill() returns. The MSI handler does not
check active at all. Teardown also releases DMA channels before
draining the tasklet.
Protect active updates and the check-and-schedule sequence with
rx_sched_lock, including the MSI path. Clear active under the lock,
then drain the tasklet before releasing DMA channels or queue entries.
QP link work is already disabled, so it cannot reactivate RX. Use a
separate lock to avoid contention with RX list operations.
Fixes: e902133162af ("ntb: stop tasklet from spinning forever during shutdown.")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Add Reviewed-by tag. No code changes.
drivers/ntb/ntb_transport.c | 50 +++++++++++++++++++++++--------------
1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 556e1d255284..30411e118a7e 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -180,6 +180,8 @@ struct ntb_transport_qp {
unsigned int rx_max_frame;
unsigned int rx_alloc_entry;
dma_cookie_t last_cookie;
+ /* Protect active and RX tasklet scheduling. */
+ spinlock_t rx_sched_lock;
struct tasklet_struct rxc_db_work;
void (*event_handler)(void *data, int status);
@@ -650,11 +652,26 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
return 0;
}
+static void ntb_transport_set_qp_active(struct ntb_transport_qp *qp, bool active)
+{
+ guard(spinlock_irqsave)(&qp->rx_sched_lock);
+
+ qp->active = active;
+}
+
+static void ntb_transport_schedule_rxc(struct ntb_transport_qp *qp)
+{
+ guard(spinlock_irqsave)(&qp->rx_sched_lock);
+
+ if (qp->active)
+ tasklet_schedule(&qp->rxc_db_work);
+}
+
static irqreturn_t ntb_transport_isr(int irq, void *dev)
{
struct ntb_transport_qp *qp = dev;
- tasklet_schedule(&qp->rxc_db_work);
+ ntb_transport_schedule_rxc(qp);
return IRQ_HANDLED;
}
@@ -896,7 +913,7 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
static void ntb_qp_link_context_reset(struct ntb_transport_qp *qp)
{
qp->link_is_up = false;
- qp->active = false;
+ ntb_transport_set_qp_active(qp, false);
qp->tx_index = 0;
qp->rx_index = 0;
@@ -1156,13 +1173,12 @@ static void ntb_qp_link_work(struct work_struct *work)
if (val & BIT(qp->qp_num)) {
dev_info(&pdev->dev, "qp %d: Link Up\n", qp->qp_num);
qp->link_is_up = true;
- qp->active = true;
+ ntb_transport_set_qp_active(qp, true);
if (qp->event_handler)
qp->event_handler(qp->cb_data, qp->link_is_up);
- if (qp->active)
- tasklet_schedule(&qp->rxc_db_work);
+ ntb_transport_schedule_rxc(qp);
} else {
ntb_transport_schedule_qp_link(qp,
msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
@@ -1190,6 +1206,7 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
qp->ndev = nt->ndev;
atomic_set(&qp->client_ready, false);
qp->event_handler = NULL;
+ spin_lock_init(&qp->rx_sched_lock);
ntb_qp_link_context_reset(qp);
if (mw_num < qp_count % mw_count)
@@ -1726,8 +1743,7 @@ static void ntb_transport_rxc_db(unsigned long data)
if (i == qp->rx_max_entry) {
/* there is more work to do */
- if (qp->active)
- tasklet_schedule(&qp->rxc_db_work);
+ ntb_transport_schedule_rxc(qp);
} else if (ntb_db_read(qp->ndev) & BIT_ULL(qp->qp_num)) {
/* the doorbell bit is set: clear it */
ntb_db_clear(qp->ndev, BIT_ULL(qp->qp_num));
@@ -1738,8 +1754,7 @@ static void ntb_transport_rxc_db(unsigned long data)
* ntb_process_rxc and clearing the doorbell bit:
* there might be some more work to do.
*/
- if (qp->active)
- tasklet_schedule(&qp->rxc_db_work);
+ ntb_transport_schedule_rxc(qp);
}
}
@@ -2206,7 +2221,11 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
disable_work_sync(&qp->link_cleanup);
disable_delayed_work_sync(&qp->link_work);
qp->link_is_up = false;
- qp->active = false;
+ ntb_transport_set_qp_active(qp, false);
+
+ qp_bit = BIT_ULL(qp->qp_num);
+ ntb_db_set_mask(qp->ndev, qp_bit);
+ tasklet_kill(&qp->rxc_db_work);
if (qp->tx_offload_thread) {
kthread_stop(qp->tx_offload_thread);
@@ -2248,11 +2267,6 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
dma_release_channel(chan);
}
- qp_bit = BIT_ULL(qp->qp_num);
-
- ntb_db_set_mask(qp->ndev, qp_bit);
- tasklet_kill(&qp->rxc_db_work);
-
qp->cb_data = NULL;
qp->rx_handler = NULL;
qp->tx_handler = NULL;
@@ -2347,8 +2361,7 @@ int ntb_transport_rx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry, &qp->rx_pend_q);
- if (qp->active)
- tasklet_schedule(&qp->rxc_db_work);
+ ntb_transport_schedule_rxc(qp);
return 0;
}
@@ -2545,8 +2558,7 @@ static void ntb_transport_doorbell_callback(void *data, int vector)
qp_num = __ffs(db_bits);
qp = &nt->qp_vec[qp_num];
- if (qp->active)
- tasklet_schedule(&qp->rxc_db_work);
+ ntb_transport_schedule_rxc(qp);
db_bits &= ~BIT_ULL(qp_num);
}
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 10/15] NTB: ntb_transport: Drain RX tasklets during link cleanup
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (8 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 09/15] NTB: ntb_transport: Stop RX tasklet scheduling " Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 11/15] NTB: ntb_transport: Wait for RX completions before resetting a QP Koichiro Den
` (4 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
ntb_qp_link_cleanup() cancels QP link work but does not wait for the RX
tasklet. The tasklet can still be processing the ring while cleanup
resets the QP, and transport link cleanup can free the MW before the
tasklet finishes.
Clear active under rx_sched_lock and drain the tasklet before resetting
the QP. Temporarily disable QP link work so a concurrent client link-up
request cannot reactivate RX during cleanup, then re-enable it for the
existing link setup paths.
This does not drain RX DMA transfers or their completion callbacks.
The next patch waits for RX DMA and its completion path to finish
accessing the MW.
Fixes: 9143595a7e05 ("NTB: ntb_transport: Free MWs in ntb_transport_link_cleanup()")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Refine commit message by adding a note on the RX DMA follow-up. (Dave)
- Add Reviewed-by tag. No code changes.
drivers/ntb/ntb_transport.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 30411e118a7e..9f71af97a8ef 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -957,11 +957,16 @@ static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
dev_info(&pdev->dev, "qp %d: Link Cleanup\n", qp->qp_num);
- cancel_delayed_work_sync(&qp->link_work);
+ disable_delayed_work_sync(&qp->link_work);
+ ntb_transport_set_qp_active(qp, false);
+ tasklet_kill(&qp->rxc_db_work);
+
ntb_qp_link_down_reset(qp);
if (qp->event_handler)
qp->event_handler(qp->cb_data, qp->link_is_up);
+
+ enable_delayed_work(&qp->link_work);
}
static void ntb_qp_link_cleanup_work(struct work_struct *work)
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 11/15] NTB: ntb_transport: Wait for RX completions before resetting a QP
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (9 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 10/15] NTB: ntb_transport: Drain RX tasklets during link cleanup Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 12/15] NTB: ntb_transport: Prepare remote RX info accesses for MW teardown Koichiro Den
` (3 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
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@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/r/20260907144257.767281F00A3A@smtp.kernel.org/
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Add Reviewed-by tag. No code changes.
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 9f71af97a8ef..8f1acf44bb53 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -950,6 +950,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;
@@ -960,6 +967,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
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 12/15] NTB: ntb_transport: Prepare remote RX info accesses for MW teardown
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (10 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 11/15] NTB: ntb_transport: Wait for RX completions before resetting a QP Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 13/15] NTB: ntb_transport: Clear QP pointers when freeing an MW Koichiro Den
` (2 subsequent siblings)
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
The next patch clears remote_rx_info when freeing its MW.
ntb_transport_tx_free_entry() and debugfs stats reads can run during
link cleanup, so make them handle a NULL pointer.
The pointer is accessed locklessly. Use READ_ONCE() and WRITE_ONCE()
to prevent compiler-induced tearing, and retain the read value so
the NULL check and dereference use the same pointer.
Also drop the redundant credit assertion in ntb_async_tx(). The caller
checks for space, but cleanup can clear remote_rx_info before this
second check.
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Drop the redundant TX credit assertion (Sashiko).
https://lore.kernel.org/r/hkrizcxjisnrkedwzycnkvhxynncgj66oj7crozf5ynuz4ys6c@7i7tixcnt2oa/
v2: https://lore.kernel.org/r/20260910040836.3792333-12-den@valinux.co.jp/
@Dave and @Logan, one-line change after Sashiko's feedback. I would
appreciate it if you could take another look, thanks.
drivers/ntb/ntb_transport.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 8f1acf44bb53..c4dfef75f159 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -490,6 +490,7 @@ EXPORT_SYMBOL_GPL(ntb_transport_unregister_client);
static int ntb_qp_debugfs_stats_show(struct seq_file *s, void *v)
{
struct ntb_transport_qp *qp = s->private;
+ struct ntb_rx_info *remote_rx_info;
if (!qp || !qp->link_is_up)
return 0;
@@ -517,7 +518,9 @@ static int ntb_qp_debugfs_stats_show(struct seq_file *s, void *v)
seq_printf(s, "tx_err_no_buf - %llu\n", qp->tx_err_no_buf);
seq_printf(s, "tx_mw - \t0x%p\n", qp->tx_mw);
seq_printf(s, "tx_index (H) - \t%u\n", qp->tx_index);
- seq_printf(s, "RRI (T) - \t%u\n", qp->remote_rx_info->entry);
+ remote_rx_info = READ_ONCE(qp->remote_rx_info);
+ if (remote_rx_info)
+ seq_printf(s, "RRI (T) - \t%u\n", remote_rx_info->entry);
seq_printf(s, "tx_max_entry - \t%u\n", qp->tx_max_entry);
seq_printf(s, "free tx - \t%u\n", ntb_transport_tx_free_entry(qp));
seq_putc(s, '\n');
@@ -612,7 +615,7 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
qp->rx_buff = mw->virt_addr + rx_size * (qp_num / mw_count);
rx_size -= sizeof(struct ntb_rx_info);
- qp->remote_rx_info = qp->rx_buff + rx_size;
+ WRITE_ONCE(qp->remote_rx_info, qp->rx_buff + rx_size);
/* Due to housekeeping, there must be atleast 2 buffs */
qp->rx_max_frame = min(transport_mtu, rx_size / 2);
@@ -935,9 +938,12 @@ static void ntb_qp_link_context_reset(struct ntb_transport_qp *qp)
static void ntb_qp_link_down_reset(struct ntb_transport_qp *qp)
{
+ struct ntb_rx_info *remote_rx_info;
+
ntb_qp_link_context_reset(qp);
- if (qp->remote_rx_info)
- qp->remote_rx_info->entry = qp->rx_max_entry - 1;
+ remote_rx_info = READ_ONCE(qp->remote_rx_info);
+ if (remote_rx_info)
+ remote_rx_info->entry = qp->rx_max_entry - 1;
}
static void ntb_transport_schedule_qp_link(struct ntb_transport_qp *qp,
@@ -1988,7 +1994,6 @@ static void ntb_async_tx(struct ntb_transport_qp *qp,
hdr = offset + qp->tx_max_frame - sizeof(struct ntb_payload_header);
entry->tx_hdr = hdr;
- WARN_ON_ONCE(!ntb_transport_tx_free_entry(qp));
WRITE_ONCE(qp->tx_index, (qp->tx_index + 1) % qp->tx_max_entry);
iowrite32(entry->len, &hdr->len);
@@ -2555,8 +2560,14 @@ EXPORT_SYMBOL_GPL(ntb_transport_max_size);
unsigned int ntb_transport_tx_free_entry(struct ntb_transport_qp *qp)
{
+ struct ntb_rx_info *remote_rx_info = READ_ONCE(qp->remote_rx_info);
unsigned int head = qp->tx_index;
- unsigned int tail = qp->remote_rx_info->entry;
+ unsigned int tail;
+
+ if (!remote_rx_info)
+ return 0;
+
+ tail = remote_rx_info->entry;
return tail >= head ? tail - head : qp->tx_max_entry + tail - head;
}
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 13/15] NTB: ntb_transport: Clear QP pointers when freeing an MW
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (11 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 12/15] NTB: ntb_transport: Prepare remote RX info accesses for MW teardown Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 14/15] NTB: ntb_transport: Abort link setup on QP MW allocation failure Koichiro Den
2026-09-28 15:25 ` [PATCH v3 15/15] NTB: ntb_transport: Remove clients before freeing transport resources Koichiro Den
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
ntb_transport_link_cleanup() frees MW buffers but leaves rx_buff and
remote_rx_info pointing into them. With a QP still allocated, another
link-down notification or transport unbind before MW setup runs again
can make ntb_qp_link_down_reset() write to freed memory through
remote_rx_info.
Clear both pointers in ntb_free_mw() for all QPs using that MW,
including those without a client. This also covers link-setup failures.
Fixes: cc79bd2738c2 ("ntb: Clean up tx tail index on link down")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
How to reproduce:
1. Load ntb_transport and ntb_netdev on both sides and establish the
transport/QP links once. Stop traffic, but leave ntb_netdev loaded
on VHOST so its QPs remain allocated throughout the test.
2. On HOST, unload ntb_netdev and ntb_transport, leaving ntb_hw_epf
bound:
modprobe -r ntb_netdev ntb_transport
Transport removal sends COMMAND_LINK_DOWN to VHOST. Wait for
ntb_transport_link_cleanup_work() to return on VHOST, using a
function-graph trace. The "Link Cleanup" message is printed before
MW release and is not sufficient to establish completion. Do not
bring the link back up before the next step.
3-(A). UAF via repeated link-down notification
Use ntb_tool on HOST to send another link-down request:
HOST# modprobe ntb_tool
HOST# echo N > "/sys/kernel/debug/ntb_tool/$ntb_host_dev/link"
==================================================================
BUG: KASAN: vmalloc-out-of-bounds in ntb_qp_link_down_reset+0x2c0..
...
Call trace:
...
__asan_report_store4_noabort+0x1c/0x28
ntb_qp_link_down_reset+0x2c0/0x2e0 [ntb_transport]
ntb_qp_link_cleanup+0xc4/0x148 [ntb_transport]
ntb_transport_link_cleanup+0x314/0x350 [ntb_transport]
ntb_transport_link_cleanup_work+0x2c/0x50 [ntb_transport]
process_one_work+0x5b8/0x12f0
...
3-(B). UAF via transport removal after link-down
VHOST# echo "$ntb_vhost_dev" > \
/sys/bus/ntb/drivers/ntb_transport/unbind
==================================================================
BUG: KASAN: vmalloc-out-of-bounds in ntb_qp_link_down_reset+0x2c0..
...
Call trace:
...
__asan_report_store4_noabort+0x1c/0x28
ntb_qp_link_down_reset+0x2c0/0x2e0 [ntb_transport]
ntb_qp_link_cleanup+0xc4/0x148 [ntb_transport]
ntb_transport_link_cleanup+0x314/0x350 [ntb_transport]
ntb_transport_free+0x68/0x588 [ntb_transport]
ntb_remove+0x5c/0xa0 [ntb]
Verified that neither test triggers a KASAN report with this patch.
Changes in v3:
- Move test details below "---". (Dave)
- Add Reviewed-by tag. No code changes.
drivers/ntb/ntb_transport.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index c4dfef75f159..9f23c9c3d220 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -782,10 +782,17 @@ static void ntb_free_mw(struct ntb_transport_ctx *nt, int num_mw)
{
struct ntb_transport_mw *mw = &nt->mw_vec[num_mw];
struct device *dma_dev = ntb_get_dma_dev(nt->ndev);
+ unsigned int i;
if (!mw->virt_addr)
return;
+ /* Drop references from every QP using this MW. */
+ for (i = num_mw; i < nt->qp_count; i += nt->mw_count) {
+ nt->qp_vec[i].rx_buff = NULL;
+ WRITE_ONCE(nt->qp_vec[i].remote_rx_info, NULL);
+ }
+
ntb_mw_clear_trans(nt->ndev, PIDX, num_mw);
dma_free_attrs(dma_dev, mw->alloc_size, mw->alloc_addr,
mw->original_dma_addr, DMA_ATTR_FORCE_CONTIGUOUS);
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 14/15] NTB: ntb_transport: Abort link setup on QP MW allocation failure
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (12 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 13/15] NTB: ntb_transport: Clear QP pointers when freeing an MW Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 15/15] NTB: ntb_transport: Remove clients before freeing transport resources Koichiro Den
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
ntb_transport_setup_qp_mw() can fail while growing a QP's RX entry pool,
but the link worker ignores that error. The worker can consequently
publish a QP whose memory-window state is only partly initialized.
Abort on the first QP setup error and release the MWs through the
existing error path instead of publishing the transport link.
Fixes: a754a8fcaf38 ("NTB: allocate number transport entries depending on size of ring size")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Add Reviewed-by tag. No code changes.
drivers/ntb/ntb_transport.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 9f23c9c3d220..af7f240479f4 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -1149,7 +1149,9 @@ static void ntb_transport_link_work(struct work_struct *work)
}
for (i = 0; i < nt->qp_count; i++) {
- ntb_transport_setup_qp_mw(nt, i);
+ rc = ntb_transport_setup_qp_mw(nt, i);
+ if (rc)
+ goto out1;
ntb_transport_setup_qp_peer_msi(nt, i);
}
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 15/15] NTB: ntb_transport: Remove clients before freeing transport resources
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
` (13 preceding siblings ...)
2026-09-28 15:25 ` [PATCH v3 14/15] NTB: ntb_transport: Abort link setup on QP MW allocation failure Koichiro Den
@ 2026-09-28 15:25 ` Koichiro Den
14 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-28 15:25 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Frank Li, Logan Gunthorpe
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
Unbinding ntb_transport can call ntb_transport_free() while ntb_netdev
is still bound. The transport frees MWs and QP resources before
unregistering the clients, so the netdev's transmit path and timer can
access freed memory. Its remove callback also calls
ntb_transport_free_queue() on a QP whose resources have already been
released. This teardown order is unsafe and somewhat unintuitive.
The crash can be reproduced with an intensive TX load, during which you
unbind the NTB device. The following is a KASAN report from my
VHOST/HOST setup using vNTB.
VHOST# sudo iperf3 -ub0 -c $HOST -l 100 -P 100 &
VHOST# echo $VHOST_NTB_DEV > /sys/bus/ntb/drivers/ntb_transport/unbind
==================================================================
BUG: KASAN: vmalloc-out-of-bounds in ntb_transport_tx_free_entry+0xf0
...
Call trace:
...
__asan_report_load4_noabort+0x1c/0x30
ntb_transport_tx_free_entry+0xf0/0x130 [ntb_transport]
ntb_netdev_tx_timer+0x78/0x260 [ntb_netdev]
...
Disable and drain transport link work first, then unregister the clients
so they stop using and release their QPs. After that, free any QPs left
over before running transport link cleanup. Disabling the work keeps
link events from restarting setup or cleanup during client removal.
Fixes: fce8a7bb5b4b ("PCI-Express Non-Transparent Bridge Support")
Cc: stable@vger.kernel.org
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Add Reviewed-by tag. No code changes.
drivers/ntb/ntb_transport.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index af7f240479f4..eef3a214d91a 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -1484,9 +1484,11 @@ static void ntb_transport_free(struct ntb_client *self, struct ntb_dev *ndev)
debugfs_remove_recursive(nt->debugfs_node_dir);
- ntb_transport_link_cleanup(nt);
- cancel_work_sync(&nt->link_cleanup);
- cancel_delayed_work_sync(&nt->link_work);
+ /* Stop transport work before clients release their QPs. */
+ disable_delayed_work_sync(&nt->link_work);
+ disable_work_sync(&nt->link_cleanup);
+
+ ntb_bus_remove(nt);
qp_bitmap_alloc = nt->qp_bitmap & ~nt->qp_bitmap_free;
@@ -1497,11 +1499,10 @@ static void ntb_transport_free(struct ntb_client *self, struct ntb_dev *ndev)
ntb_transport_free_queue(qp);
}
+ ntb_transport_link_cleanup(nt);
ntb_link_disable(ndev);
ntb_clear_ctx(ndev);
- ntb_bus_remove(nt);
-
for (i = nt->mw_count; i--; ) {
ntb_free_mw(nt, i);
iounmap(nt->mw_vec[i].vbase);
--
2.51.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 03/15] NTB: ntb_transport: Make link setup flags atomic
2026-09-28 15:25 ` [PATCH v3 03/15] NTB: ntb_transport: Make link setup flags atomic Koichiro Den
@ 2026-09-28 15:53 ` Logan Gunthorpe
0 siblings, 0 replies; 19+ messages in thread
From: Logan Gunthorpe @ 2026-09-28 15:53 UTC (permalink / raw)
To: Koichiro Den, Jon Mason, Dave Jiang, Allen Hubbe, Frank Li
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
On 2026-09-28 09:25, Koichiro Den wrote:
> Convert nt->link_is_up and qp->client_ready to atomic_t and use atomic
> accessors throughout. This prepares for the unlocked cleanup check and
> the link-up ordering fixes that follow.
>
> Leave control flow and locking unchanged.
>
> Cc: stable@vger.kernel.org
> Suggested-by: Frank Li <Frank.Li@kernel.org>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 06/15] NTB: ntb_transport: Avoid losing QP link-up requests
2026-09-28 15:25 ` [PATCH v3 06/15] NTB: ntb_transport: Avoid losing QP link-up requests Koichiro Den
@ 2026-09-28 16:57 ` Logan Gunthorpe
2026-09-29 1:43 ` Koichiro Den
0 siblings, 1 reply; 19+ messages in thread
From: Logan Gunthorpe @ 2026-09-28 16:57 UTC (permalink / raw)
To: Koichiro Den, Jon Mason, Dave Jiang, Allen Hubbe, Frank Li
Cc: fuyuanli, Greg Kroah-Hartman, Nicholas Bellinger, Joey Zhang,
ntb, linux-kernel, stable
On 2026-09-28 09:25, Koichiro Den wrote:
> ntb_netdev_open() can call ntb_transport_link_up() while the transport
> worker is completing setup on another CPU. Concurrent transport setup
> and a client link-up request can both read the other's flag as false and
> leave QP link work unqueued. The QP then stays down until another link
> event or client link-up request.
>
> This is the store-buffering pattern described in
> tools/memory-model/Documentation/recipes.txt ("Store buffering").
>
> Add a full barrier between the store and load on each side.
>
> Fixes: fce8a7bb5b4b ("PCI-Express Non-Transparent Bridge Support")
> Cc: stable@vger.kernel.org
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Link: https://lore.kernel.org/r/20260907144701.702E41F00A3A@smtp.kernel.org/
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
Thanks, I find smp_mb calls difficult to understand, but I think these
are correct. I expect I ran into this problem a few times back when I
was working on this code and had no idea the cause or how to fix it.
I have one minor suggestion below for the comment, other than that:
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
> diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
> index 51d9e9969065..d290e5869c21 100644
> --- a/drivers/ntb/ntb_transport.c
> +++ b/drivers/ntb/ntb_transport.c
> @@ -1101,6 +1101,12 @@ static void ntb_transport_link_work(struct work_struct *work)
> /* Publish the link only after every QP has been set up. */
> atomic_set_release(&nt->link_is_up, true);
>
> + /*
> + * Prevent both sides from missing each other's flag. Pairs with
> + * the barrier in ntb_transport_link_up().
> + */
> + smp_mb();
> +
I don't find this comment all that easy to understand. Can we expand it
a little? Maybe something like:
Order the link_is_up store before the client_ready loads below, so
that this path or ntb_transport_link_up() is guaranteed to see the
other's flag. Pairs with smp_mb() in ntb_transport_link_up().
Thanks,
Logan
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 06/15] NTB: ntb_transport: Avoid losing QP link-up requests
2026-09-28 16:57 ` Logan Gunthorpe
@ 2026-09-29 1:43 ` Koichiro Den
0 siblings, 0 replies; 19+ messages in thread
From: Koichiro Den @ 2026-09-29 1:43 UTC (permalink / raw)
To: Logan Gunthorpe, Jon Mason, Dave Jiang
Cc: Allen Hubbe, Frank Li, fuyuanli, Greg Kroah-Hartman,
Nicholas Bellinger, Joey Zhang, ntb, linux-kernel, stable
On Mon, Sep 28, 2026 at 10:57:12AM -0600, Logan Gunthorpe wrote:
>
>
> On 2026-09-28 09:25, Koichiro Den wrote:
> > ntb_netdev_open() can call ntb_transport_link_up() while the transport
> > worker is completing setup on another CPU. Concurrent transport setup
> > and a client link-up request can both read the other's flag as false and
> > leave QP link work unqueued. The QP then stays down until another link
> > event or client link-up request.
> >
> > This is the store-buffering pattern described in
> > tools/memory-model/Documentation/recipes.txt ("Store buffering").
> >
> > Add a full barrier between the store and load on each side.
> >
> > Fixes: fce8a7bb5b4b ("PCI-Express Non-Transparent Bridge Support")
> > Cc: stable@vger.kernel.org
> > Reported-by: Sashiko <sashiko-bot@kernel.org>
> > Link: https://lore.kernel.org/r/20260907144701.702E41F00A3A@smtp.kernel.org/
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
>
> Thanks, I find smp_mb calls difficult to understand, but I think these
> are correct. I expect I ran into this problem a few times back when I
> was working on this code and had no idea the cause or how to fix it.
>
> I have one minor suggestion below for the comment, other than that:
>
> Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Hi Logan, thanks for the review.
>
>
> > diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
> > index 51d9e9969065..d290e5869c21 100644
> > --- a/drivers/ntb/ntb_transport.c
> > +++ b/drivers/ntb/ntb_transport.c
> > @@ -1101,6 +1101,12 @@ static void ntb_transport_link_work(struct work_struct *work)
> > /* Publish the link only after every QP has been set up. */
> > atomic_set_release(&nt->link_is_up, true);
> >
> > + /*
> > + * Prevent both sides from missing each other's flag. Pairs with
> > + * the barrier in ntb_transport_link_up().
> > + */
> > + smp_mb();
> > +
>
> I don't find this comment all that easy to understand. Can we expand it
> a little? Maybe something like:
>
> Order the link_is_up store before the client_ready loads below, so
> that this path or ntb_transport_link_up() is guaranteed to see the
> other's flag. Pairs with smp_mb() in ntb_transport_link_up().
That's great. I think we can use it as-is.
I've gone through Sashiko's feedback on v3, and I don't think another respin is
needed for those points.
Jon, Dave, if v3 looks good to you, could you apply it with the comment updated
as Logan suggested? Of course, I'm happy to send v4 with that change if you'd
prefer.
Best regards,
Koichiro
>
>
> Thanks,
>
> Logan
>
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-09-29 1:43 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-28 15:25 [PATCH v3 00/15] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
2026-09-28 15:25 ` [PATCH v3 01/15] NTB: ntb_transport: Remove the device debugfs directory Koichiro Den
2026-09-28 15:25 ` [PATCH v3 02/15] NTB: ntb_transport: Start TX offload thread after queue setup Koichiro Den
2026-09-28 15:25 ` [PATCH v3 03/15] NTB: ntb_transport: Make link setup flags atomic Koichiro Den
2026-09-28 15:53 ` Logan Gunthorpe
2026-09-28 15:25 ` [PATCH v3 04/15] NTB: ntb_transport: Avoid deadlock when cancelling link work Koichiro Den
2026-09-28 15:25 ` [PATCH v3 05/15] NTB: ntb_transport: Publish link state after QP setup Koichiro Den
2026-09-28 15:25 ` [PATCH v3 06/15] NTB: ntb_transport: Avoid losing QP link-up requests Koichiro Den
2026-09-28 16:57 ` Logan Gunthorpe
2026-09-29 1:43 ` Koichiro Den
2026-09-28 15:25 ` [PATCH v3 07/15] NTB: ntb_transport: Clear link state before QP cleanup Koichiro Den
2026-09-28 15:25 ` [PATCH v3 08/15] NTB: ntb_transport: Stop QP work before freeing a queue Koichiro Den
2026-09-28 15:25 ` [PATCH v3 09/15] NTB: ntb_transport: Stop RX tasklet scheduling " Koichiro Den
2026-09-28 15:25 ` [PATCH v3 10/15] NTB: ntb_transport: Drain RX tasklets during link cleanup Koichiro Den
2026-09-28 15:25 ` [PATCH v3 11/15] NTB: ntb_transport: Wait for RX completions before resetting a QP Koichiro Den
2026-09-28 15:25 ` [PATCH v3 12/15] NTB: ntb_transport: Prepare remote RX info accesses for MW teardown Koichiro Den
2026-09-28 15:25 ` [PATCH v3 13/15] NTB: ntb_transport: Clear QP pointers when freeing an MW Koichiro Den
2026-09-28 15:25 ` [PATCH v3 14/15] NTB: ntb_transport: Abort link setup on QP MW allocation failure Koichiro Den
2026-09-28 15:25 ` [PATCH v3 15/15] NTB: ntb_transport: Remove clients before freeing transport resources Koichiro Den
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®