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 <ubraun@linux.ibm.com> Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2c1d3e5030
commit
6a37ad3da5
|
@ -548,6 +548,8 @@ static void smc_conn_kill(struct smc_connection *conn, bool soft)
|
|||
tasklet_kill(&conn->rx_tsklet);
|
||||
else
|
||||
tasklet_unlock_wait(&conn->rx_tsklet);
|
||||
} else {
|
||||
smc_cdc_tx_dismiss_slots(conn);
|
||||
}
|
||||
smc_lgr_unregister_conn(conn);
|
||||
smc_close_active_abort(smc);
|
||||
|
|
|
@ -520,9 +520,9 @@ static void smc_ib_cleanup_per_ibdev(struct smc_ib_device *smcibdev)
|
|||
if (!smcibdev->initialized)
|
||||
return;
|
||||
smcibdev->initialized = 0;
|
||||
smc_wr_remove_dev(smcibdev);
|
||||
ib_destroy_cq(smcibdev->roce_cq_recv);
|
||||
ib_destroy_cq(smcibdev->roce_cq_send);
|
||||
smc_wr_remove_dev(smcibdev);
|
||||
}
|
||||
|
||||
static struct ib_client smc_ib_client;
|
||||
|
|
|
@ -50,6 +50,26 @@ struct smc_wr_tx_pend { /* control data for a pending send request */
|
|||
|
||||
/*------------------------------- completion --------------------------------*/
|
||||
|
||||
/* returns true if at least one tx work request is pending on the given link */
|
||||
static inline bool smc_wr_is_tx_pend(struct smc_link *link)
|
||||
{
|
||||
if (find_first_bit(link->wr_tx_mask, link->wr_tx_cnt) !=
|
||||
link->wr_tx_cnt) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* wait till all pending tx work requests on the given link are completed */
|
||||
static inline int smc_wr_tx_wait_no_pending_sends(struct smc_link *link)
|
||||
{
|
||||
if (wait_event_timeout(link->wr_tx_wait, !smc_wr_is_tx_pend(link),
|
||||
SMC_WR_TX_WAIT_PENDING_TIME))
|
||||
return 0;
|
||||
else /* timeout */
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
static inline int smc_wr_tx_find_pending_index(struct smc_link *link, u64 wr_id)
|
||||
{
|
||||
u32 i;
|
||||
|
@ -229,6 +249,7 @@ int smc_wr_tx_put_slot(struct smc_link *link,
|
|||
memset(&link->wr_tx_bufs[idx], 0,
|
||||
sizeof(link->wr_tx_bufs[idx]));
|
||||
test_and_clear_bit(idx, link->wr_tx_mask);
|
||||
wake_up(&link->wr_tx_wait);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -512,8 +533,10 @@ void smc_wr_free_link(struct smc_link *lnk)
|
|||
{
|
||||
struct ib_device *ibdev;
|
||||
|
||||
memset(lnk->wr_tx_mask, 0,
|
||||
BITS_TO_LONGS(SMC_WR_BUF_CNT) * sizeof(*lnk->wr_tx_mask));
|
||||
if (smc_wr_tx_wait_no_pending_sends(lnk))
|
||||
memset(lnk->wr_tx_mask, 0,
|
||||
BITS_TO_LONGS(SMC_WR_BUF_CNT) *
|
||||
sizeof(*lnk->wr_tx_mask));
|
||||
|
||||
if (!lnk->smcibdev)
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue