Commit b7eede75 authored by Karsten Graul's avatar Karsten Graul Committed by David S. Miller

net/smc: fix work request handling

Wait for pending sends only when smc_switch_conns() found a link to move
the connections to. Do not wait during link freeing, this can lead to
permanent hang situations. And refuse to provide a new tx slot on an
unusable link.

Fixes: c6f02ebe ("net/smc: switch connections to alternate link")
Reviewed-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6778a6be
...@@ -1241,7 +1241,7 @@ static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr) ...@@ -1241,7 +1241,7 @@ static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr)
smc_llc_send_message(lnk, &qentry->msg); /* response */ smc_llc_send_message(lnk, &qentry->msg); /* response */
if (smc_link_downing(&lnk_del->state)) { if (smc_link_downing(&lnk_del->state)) {
smc_switch_conns(lgr, lnk_del, false); if (smc_switch_conns(lgr, lnk_del, false))
smc_wr_tx_wait_no_pending_sends(lnk_del); smc_wr_tx_wait_no_pending_sends(lnk_del);
} }
smcr_link_clear(lnk_del, true); smcr_link_clear(lnk_del, true);
...@@ -1316,7 +1316,7 @@ static void smc_llc_process_srv_delete_link(struct smc_link_group *lgr) ...@@ -1316,7 +1316,7 @@ static void smc_llc_process_srv_delete_link(struct smc_link_group *lgr)
goto out; /* asymmetric link already deleted */ goto out; /* asymmetric link already deleted */
if (smc_link_downing(&lnk_del->state)) { if (smc_link_downing(&lnk_del->state)) {
smc_switch_conns(lgr, lnk_del, false); if (smc_switch_conns(lgr, lnk_del, false))
smc_wr_tx_wait_no_pending_sends(lnk_del); smc_wr_tx_wait_no_pending_sends(lnk_del);
} }
if (!list_empty(&lgr->list)) { if (!list_empty(&lgr->list)) {
......
...@@ -169,6 +169,8 @@ void smc_wr_tx_cq_handler(struct ib_cq *ib_cq, void *cq_context) ...@@ -169,6 +169,8 @@ void smc_wr_tx_cq_handler(struct ib_cq *ib_cq, void *cq_context)
static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx) static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
{ {
*idx = link->wr_tx_cnt; *idx = link->wr_tx_cnt;
if (!smc_link_usable(link))
return -ENOLINK;
for_each_clear_bit(*idx, link->wr_tx_mask, link->wr_tx_cnt) { for_each_clear_bit(*idx, link->wr_tx_mask, link->wr_tx_cnt) {
if (!test_and_set_bit(*idx, link->wr_tx_mask)) if (!test_and_set_bit(*idx, link->wr_tx_mask))
return 0; return 0;
...@@ -560,15 +562,15 @@ void smc_wr_free_link(struct smc_link *lnk) ...@@ -560,15 +562,15 @@ void smc_wr_free_link(struct smc_link *lnk)
{ {
struct ib_device *ibdev; struct ib_device *ibdev;
if (!lnk->smcibdev)
return;
ibdev = lnk->smcibdev->ibdev;
if (smc_wr_tx_wait_no_pending_sends(lnk)) if (smc_wr_tx_wait_no_pending_sends(lnk))
memset(lnk->wr_tx_mask, 0, memset(lnk->wr_tx_mask, 0,
BITS_TO_LONGS(SMC_WR_BUF_CNT) * BITS_TO_LONGS(SMC_WR_BUF_CNT) *
sizeof(*lnk->wr_tx_mask)); sizeof(*lnk->wr_tx_mask));
if (!lnk->smcibdev)
return;
ibdev = lnk->smcibdev->ibdev;
if (lnk->wr_rx_dma_addr) { if (lnk->wr_rx_dma_addr) {
ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr, ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
SMC_WR_BUF_SIZE * lnk->wr_rx_cnt, SMC_WR_BUF_SIZE * lnk->wr_rx_cnt,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment