net/smc: make wait for work request uninterruptible

Work requests are needed for every ib_post_send(), among them the
ib_post_send() to signal closing. If an smc socket program is cancelled,
the smc connections should be cleaned up, and require sending of closing
signals to the peer. This may fail, if a wait for
a free work request is needed, but is cancelled immediately due to the
cancel interrupt. To guarantee notification of the peer, the wait for
a work request is changed to uninterruptible.

And the area to receive work request completion info with
ib_poll_cq() is cleared first.
And _tx_ variable names are used in the _tx_routines for the
demultiplexing common type in the header.

Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Ursula Braun 2018-01-24 10:28:15 +01:00 коммит произвёл David S. Miller
Родитель 8429c13435
Коммит 86e780d3a3
1 изменённых файлов: 6 добавлений и 7 удалений

Просмотреть файл

@ -122,6 +122,7 @@ static void smc_wr_tx_tasklet_fn(unsigned long data)
again: again:
polled++; polled++;
do { do {
memset(&wc, 0, sizeof(wc));
rc = ib_poll_cq(dev->roce_cq_send, SMC_WR_MAX_POLL_CQE, wc); rc = ib_poll_cq(dev->roce_cq_send, SMC_WR_MAX_POLL_CQE, wc);
if (polled == 1) { if (polled == 1) {
ib_req_notify_cq(dev->roce_cq_send, ib_req_notify_cq(dev->roce_cq_send,
@ -185,7 +186,7 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
if (rc) if (rc)
return rc; return rc;
} else { } else {
rc = wait_event_interruptible_timeout( rc = wait_event_timeout(
link->wr_tx_wait, link->wr_tx_wait,
(smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY), (smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY),
SMC_WR_TX_WAIT_FREE_SLOT_TIME); SMC_WR_TX_WAIT_FREE_SLOT_TIME);
@ -198,8 +199,6 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
smc_lgr_terminate(lgr); smc_lgr_terminate(lgr);
return -EPIPE; return -EPIPE;
} }
if (rc == -ERESTARTSYS)
return -EINTR;
if (idx == link->wr_tx_cnt) if (idx == link->wr_tx_cnt)
return -EPIPE; return -EPIPE;
} }
@ -300,18 +299,18 @@ int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr)
return rc; return rc;
} }
void smc_wr_tx_dismiss_slots(struct smc_link *link, u8 wr_rx_hdr_type, void smc_wr_tx_dismiss_slots(struct smc_link *link, u8 wr_tx_hdr_type,
smc_wr_tx_filter filter, smc_wr_tx_filter filter,
smc_wr_tx_dismisser dismisser, smc_wr_tx_dismisser dismisser,
unsigned long data) unsigned long data)
{ {
struct smc_wr_tx_pend_priv *tx_pend; struct smc_wr_tx_pend_priv *tx_pend;
struct smc_wr_rx_hdr *wr_rx; struct smc_wr_rx_hdr *wr_tx;
int i; int i;
for_each_set_bit(i, link->wr_tx_mask, link->wr_tx_cnt) { for_each_set_bit(i, link->wr_tx_mask, link->wr_tx_cnt) {
wr_rx = (struct smc_wr_rx_hdr *)&link->wr_rx_bufs[i]; wr_tx = (struct smc_wr_rx_hdr *)&link->wr_tx_bufs[i];
if (wr_rx->type != wr_rx_hdr_type) if (wr_tx->type != wr_tx_hdr_type)
continue; continue;
tx_pend = &link->wr_tx_pends[i].priv; tx_pend = &link->wr_tx_pends[i].priv;
if (filter(tx_pend, data)) if (filter(tx_pend, data))