aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoi Dayan <roid@mellanox.com>2014-04-01 09:28:38 -0400
committerRoland Dreier <roland@purestorage.com>2014-04-01 14:09:46 -0400
commit1d6c2b736fd251c1f827704b1234d81b28c112d6 (patch)
treee2d21beff3ae208830a32f750d3c97e24d99cae9
parent39c978cd1704dc03f6913bd40f858def7fd31185 (diff)
IB/iser: Drain the tx cq once before looping on the rx cq
The iser disconnection flow isn't done before all the inflight recv/send buffers posted to the QP are either flushed or normally completed to the CQ that serves this connection. The condition check is done in iser_handle_comp_error(). Currently, it's possible for the send buffer completion that makes the posted send buffers counter reach zero to be polled in the drain tx call, which is after the rx cq is fully drained. Since this completion might be not an error one (for example, it might be a completion of the logout request iSCSI PDU) we will skip iser_handle_comp_error(). So the connection will never terminate from the iscsi stack point of view, and we hang. To resolve this race, do the draining of the tx cq before the loop on the rx cq. Signed-off-by: Roi Dayan <roid@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index d2848e4e4274..89fadd85a776 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -1112,8 +1112,12 @@ static void iser_cq_tasklet_fn(unsigned long data)
1112 struct iser_rx_desc *desc; 1112 struct iser_rx_desc *desc;
1113 unsigned long xfer_len; 1113 unsigned long xfer_len;
1114 struct iser_conn *ib_conn; 1114 struct iser_conn *ib_conn;
1115 int completed_tx, completed_rx; 1115 int completed_tx, completed_rx = 0;
1116 completed_tx = completed_rx = 0; 1116
1117 /* First do tx drain, so in a case where we have rx flushes and a successful
1118 * tx completion we will still go through completion error handling.
1119 */
1120 completed_tx = iser_drain_tx_cq(device, cq_index);
1117 1121
1118 while (ib_poll_cq(cq, 1, &wc) == 1) { 1122 while (ib_poll_cq(cq, 1, &wc) == 1) {
1119 desc = (struct iser_rx_desc *) (unsigned long) wc.wr_id; 1123 desc = (struct iser_rx_desc *) (unsigned long) wc.wr_id;
@@ -1141,7 +1145,6 @@ static void iser_cq_tasklet_fn(unsigned long data)
1141 * " would not cause interrupts to be missed" */ 1145 * " would not cause interrupts to be missed" */
1142 ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); 1146 ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
1143 1147
1144 completed_tx += iser_drain_tx_cq(device, cq_index);
1145 iser_dbg("got %d rx %d tx completions\n", completed_rx, completed_tx); 1148 iser_dbg("got %d rx %d tx completions\n", completed_rx, completed_tx);
1146} 1149}
1147 1150