Skip to content

Commit 6a37ad3

Browse files
Ursula Braundavem330
authored andcommitted
net/smc: wait for tx completions before link freeing
Make sure all pending work requests are completed before freeing a link. Dismiss tx pending slots already when terminating a link group to exploit termination shortcut in tx completion queue handler. And kill the completion queue tasklets after destroy of the completion queues, otherwise there is a time window for another tasklet schedule of an already killed tasklet. Signed-off-by: Ursula Braun <[email protected]> Signed-off-by: Karsten Graul <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2c1d3e5 commit 6a37ad3

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

net/smc/smc_core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,8 @@ static void smc_conn_kill(struct smc_connection *conn, bool soft)
548548
tasklet_kill(&conn->rx_tsklet);
549549
else
550550
tasklet_unlock_wait(&conn->rx_tsklet);
551+
} else {
552+
smc_cdc_tx_dismiss_slots(conn);
551553
}
552554
smc_lgr_unregister_conn(conn);
553555
smc_close_active_abort(smc);

net/smc/smc_ib.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,9 @@ static void smc_ib_cleanup_per_ibdev(struct smc_ib_device *smcibdev)
520520
if (!smcibdev->initialized)
521521
return;
522522
smcibdev->initialized = 0;
523-
smc_wr_remove_dev(smcibdev);
524523
ib_destroy_cq(smcibdev->roce_cq_recv);
525524
ib_destroy_cq(smcibdev->roce_cq_send);
525+
smc_wr_remove_dev(smcibdev);
526526
}
527527

528528
static struct ib_client smc_ib_client;

net/smc/smc_wr.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,26 @@ struct smc_wr_tx_pend { /* control data for a pending send request */
5050

5151
/*------------------------------- completion --------------------------------*/
5252

53+
/* returns true if at least one tx work request is pending on the given link */
54+
static inline bool smc_wr_is_tx_pend(struct smc_link *link)
55+
{
56+
if (find_first_bit(link->wr_tx_mask, link->wr_tx_cnt) !=
57+
link->wr_tx_cnt) {
58+
return true;
59+
}
60+
return false;
61+
}
62+
63+
/* wait till all pending tx work requests on the given link are completed */
64+
static inline int smc_wr_tx_wait_no_pending_sends(struct smc_link *link)
65+
{
66+
if (wait_event_timeout(link->wr_tx_wait, !smc_wr_is_tx_pend(link),
67+
SMC_WR_TX_WAIT_PENDING_TIME))
68+
return 0;
69+
else /* timeout */
70+
return -EPIPE;
71+
}
72+
5373
static inline int smc_wr_tx_find_pending_index(struct smc_link *link, u64 wr_id)
5474
{
5575
u32 i;
@@ -229,6 +249,7 @@ int smc_wr_tx_put_slot(struct smc_link *link,
229249
memset(&link->wr_tx_bufs[idx], 0,
230250
sizeof(link->wr_tx_bufs[idx]));
231251
test_and_clear_bit(idx, link->wr_tx_mask);
252+
wake_up(&link->wr_tx_wait);
232253
return 1;
233254
}
234255

@@ -512,8 +533,10 @@ void smc_wr_free_link(struct smc_link *lnk)
512533
{
513534
struct ib_device *ibdev;
514535

515-
memset(lnk->wr_tx_mask, 0,
516-
BITS_TO_LONGS(SMC_WR_BUF_CNT) * sizeof(*lnk->wr_tx_mask));
536+
if (smc_wr_tx_wait_no_pending_sends(lnk))
537+
memset(lnk->wr_tx_mask, 0,
538+
BITS_TO_LONGS(SMC_WR_BUF_CNT) *
539+
sizeof(*lnk->wr_tx_mask));
517540

518541
if (!lnk->smcibdev)
519542
return;

0 commit comments

Comments
 (0)