* [PATCH net-next v1 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot()
2026-08-06 6:42 [PATCH net-next v1 0/2] net/smc: fix v2 slot clearing and reduce TX slot contention D. Wythe
@ 2026-08-06 6:42 ` D. Wythe
2026-08-06 6:42 ` [PATCH net-next v1 2/2] net/smc: reduce TX slot contention with exclusive wait D. Wythe
1 sibling, 0 replies; 4+ messages in thread
From: D. Wythe @ 2026-08-06 6:42 UTC (permalink / raw)
To: mjambigi, wenjia, wintera, dust.li, tonylu, guwen
Cc: kuba, davem, netdev, linux-s390, linux-rdma, leonro, pabeni,
edumazet, sidraya, jaka, oliver.yang
smc_wr_tx_put_slot() tries to reset the v2 pending slot and buffer with
memset(&link->wr_tx_v2_pend, 0, sizeof(link->wr_tx_v2_pend)) and the
equivalent for wr_tx_buf_v2. Both are pointers, so this zeroes the 8-byte
pointer variable instead of the structure it points to. The pending slot
and buffer are therefore never actually cleared, and the pointers get
overwritten with NULL.
Pass the pointers directly and use sizeof(*pointer) so the intended
structures are cleared.
Fixes: 8799e310fb3f ("net/smc: add v2 support to the work request layer")
Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
---
net/smc/smc_wr.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c
index 59c92b46945c..6b5add922993 100644
--- a/net/smc/smc_wr.c
+++ b/net/smc/smc_wr.c
@@ -288,10 +288,10 @@ int smc_wr_tx_put_slot(struct smc_link *link,
} else if (link->lgr->smc_version == SMC_V2 &&
pend->idx == link->wr_tx_cnt) {
/* Large v2 buffer */
- memset(&link->wr_tx_v2_pend, 0,
- sizeof(link->wr_tx_v2_pend));
- memset(&link->lgr->wr_tx_buf_v2, 0,
- sizeof(link->lgr->wr_tx_buf_v2));
+ memset(link->wr_tx_v2_pend, 0,
+ sizeof(*link->wr_tx_v2_pend));
+ memset(link->lgr->wr_tx_buf_v2, 0,
+ sizeof(*link->lgr->wr_tx_buf_v2));
return 1;
}
--
2.45.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH net-next v1 2/2] net/smc: reduce TX slot contention with exclusive wait
2026-08-06 6:42 [PATCH net-next v1 0/2] net/smc: fix v2 slot clearing and reduce TX slot contention D. Wythe
2026-08-06 6:42 ` [PATCH net-next v1 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() D. Wythe
@ 2026-08-06 6:42 ` D. Wythe
2026-08-07 5:45 ` Mahanta Jambigi
1 sibling, 1 reply; 4+ messages in thread
From: D. Wythe @ 2026-08-06 6:42 UTC (permalink / raw)
To: mjambigi, wenjia, wintera, dust.li, tonylu, guwen
Cc: kuba, davem, netdev, linux-s390, linux-rdma, leonro, pabeni,
edumazet, sidraya, jaka, oliver.yang
smc_wr_tx_get_free_slot() waits for a free TX slot with
wait_event_interruptible_timeout(). Since the wait_event family
enqueues waiters as non-exclusive, wake_up() may wake multiple
waiters even though only one can use the slot, causing
thundering-herd contention when slots are scarce.
Use an exclusive wait loop with prepare_to_wait_exclusive() so
wake_up() wakes only one waiter per freed slot.
smc_wr_wakeup_tx_wait() still uses wake_up_all() during link
teardown, so teardown behavior is unchanged.
This also corrects the return value on a pending signal: the previous
wait_event_interruptible_timeout() path fell through to the "no free
slot" case and returned -EPIPE, masking the signal as a connection
error. The open-coded loop now returns -ERESTARTSYS, matching the
standard interruptible-wait semantics and letting the syscall restart
machinery handle it.
Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
Reviewed-by: Wen Gu <guwen@linux.alibaba.com>
---
net/smc/smc_wr.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c
index 6b5add922993..2cdd4063c13d 100644
--- a/net/smc/smc_wr.c
+++ b/net/smc/smc_wr.c
@@ -198,11 +198,13 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
struct smc_rdma_wr **wr_rdma_buf,
struct smc_wr_tx_pend_priv **wr_pend_priv)
{
+ unsigned long timeout = SMC_WR_TX_WAIT_FREE_SLOT_TIME;
struct smc_link_group *lgr = smc_get_lgr(link);
struct smc_wr_tx_pend *wr_pend;
u32 idx = link->wr_tx_cnt;
struct ib_send_wr *wr_ib;
u64 wr_id;
+ DEFINE_WAIT(wait);
int rc;
*wr_buf = NULL;
@@ -212,17 +214,31 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
if (rc)
return rc;
} else {
- rc = wait_event_interruptible_timeout(
- link->wr_tx_wait,
- !smc_link_sendable(link) ||
- lgr->terminating ||
- (smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY),
- SMC_WR_TX_WAIT_FREE_SLOT_TIME);
- if (!rc) {
- /* timeout - terminate link */
- smcr_link_down_cond_sched(link);
- return -EPIPE;
+ rc = 0;
+ for (;;) {
+ prepare_to_wait_exclusive(&link->wr_tx_wait, &wait,
+ TASK_INTERRUPTIBLE);
+ if (!smc_link_sendable(link) || lgr->terminating ||
+ smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY)
+ break;
+ timeout = schedule_timeout(timeout);
+ /* re-check */
+ if (!smc_link_sendable(link) || lgr->terminating ||
+ smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY)
+ break;
+ if (!timeout) {
+ /* timeout - terminate link */
+ smcr_link_down_cond_sched(link);
+ break;
+ }
+ if (signal_pending(current)) {
+ rc = -ERESTARTSYS;
+ break;
+ }
}
+ finish_wait(&link->wr_tx_wait, &wait);
+ if (rc)
+ return rc;
if (idx == link->wr_tx_cnt)
return -EPIPE;
}
--
2.45.0
^ permalink raw reply related [flat|nested] 4+ messages in thread