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:
Родитель
8429c13435
Коммит
86e780d3a3
|
@ -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))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче