aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2014-10-01 07:02:10 -0400
committerRoland Dreier <roland@purestorage.com>2014-10-09 03:06:07 -0400
commitff3dd52d267165347d6f92a90016e692d074a00c (patch)
tree2edd94cf4b5c3974e6f475e7b82714e9367b09fc
parent6aabfa76f5e5281e5db128a34420d8f33b8574f7 (diff)
IB/iser: Use beacon to indicate all completions were consumed
Avoid post_send counting (atomic) in the IO path just to keep track of how many completions we need to consume. Use a beacon post to indicate that all prior posts completed. Signed-off-by: Sagi Grimberg <sagig@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/iscsi_iser.h5
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c8
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c32
3 files changed, 23 insertions, 22 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 1617c5cce8b1..4fcb25604d80 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -150,6 +150,7 @@
150#define ISER_RSV 0x04 150#define ISER_RSV 0x04
151 151
152#define ISER_FASTREG_LI_WRID 0xffffffffffffffffULL 152#define ISER_FASTREG_LI_WRID 0xffffffffffffffffULL
153#define ISER_BEACON_WRID 0xfffffffffffffffeULL
153 154
154struct iser_hdr { 155struct iser_hdr {
155 u8 flags; 156 u8 flags;
@@ -335,11 +336,11 @@ struct fast_reg_descriptor {
335 * @cma_id: rdma_cm connection maneger handle 336 * @cma_id: rdma_cm connection maneger handle
336 * @qp: Connection Queue-pair 337 * @qp: Connection Queue-pair
337 * @post_recv_buf_count: post receive counter 338 * @post_recv_buf_count: post receive counter
338 * @post_send_buf_count: post send counter
339 * @rx_wr: receive work request for batch posts 339 * @rx_wr: receive work request for batch posts
340 * @device: reference to iser device 340 * @device: reference to iser device
341 * @comp: iser completion context 341 * @comp: iser completion context
342 * @pi_support: Indicate device T10-PI support 342 * @pi_support: Indicate device T10-PI support
343 * @beacon: beacon send wr to signal all flush errors were drained
343 * @flush_comp: completes when all connection completions consumed 344 * @flush_comp: completes when all connection completions consumed
344 * @lock: protects fmr/fastreg pool 345 * @lock: protects fmr/fastreg pool
345 * @union.fmr: 346 * @union.fmr:
@@ -355,11 +356,11 @@ struct ib_conn {
355 struct rdma_cm_id *cma_id; 356 struct rdma_cm_id *cma_id;
356 struct ib_qp *qp; 357 struct ib_qp *qp;
357 int post_recv_buf_count; 358 int post_recv_buf_count;
358 atomic_t post_send_buf_count;
359 struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX]; 359 struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX];
360 struct iser_device *device; 360 struct iser_device *device;
361 struct iser_comp *comp; 361 struct iser_comp *comp;
362 bool pi_support; 362 bool pi_support;
363 struct ib_send_wr beacon;
363 struct completion flush_comp; 364 struct completion flush_comp;
364 spinlock_t lock; 365 spinlock_t lock;
365 union { 366 union {
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 359c0b84f1ac..ffbdf922587a 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -350,12 +350,10 @@ static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req)
350 return 0; 350 return 0;
351 351
352 /* 352 /*
353 * Check that there is one posted recv buffer (for the last login 353 * Check that there is one posted recv buffer
354 * response) and no posted send buffers left - they must have been 354 * (for the last login response).
355 * consumed during previous login phases.
356 */ 355 */
357 WARN_ON(ib_conn->post_recv_buf_count != 1); 356 WARN_ON(ib_conn->post_recv_buf_count != 1);
358 WARN_ON(atomic_read(&ib_conn->post_send_buf_count) != 0);
359 357
360 if (session->discovery_sess) { 358 if (session->discovery_sess) {
361 iser_info("Discovery session, re-using login RX buffer\n"); 359 iser_info("Discovery session, re-using login RX buffer\n");
@@ -634,8 +632,6 @@ void iser_snd_completion(struct iser_tx_desc *tx_desc,
634 tx_desc = NULL; 632 tx_desc = NULL;
635 } 633 }
636 634
637 atomic_dec(&ib_conn->post_send_buf_count);
638
639 if (tx_desc && tx_desc->type == ISCSI_TX_CONTROL) { 635 if (tx_desc && tx_desc->type == ISCSI_TX_CONTROL) {
640 /* this arithmetic is legal by libiscsi dd_data allocation */ 636 /* this arithmetic is legal by libiscsi dd_data allocation */
641 task = (void *) ((long)(void *)tx_desc - 637 task = (void *) ((long)(void *)tx_desc -
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index eedc27a0d3c3..805a9bdc9520 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -41,7 +41,8 @@
41#define ISCSI_ISER_MAX_CONN 8 41#define ISCSI_ISER_MAX_CONN 8
42#define ISER_MAX_RX_LEN (ISER_QP_MAX_RECV_DTOS * ISCSI_ISER_MAX_CONN) 42#define ISER_MAX_RX_LEN (ISER_QP_MAX_RECV_DTOS * ISCSI_ISER_MAX_CONN)
43#define ISER_MAX_TX_LEN (ISER_QP_MAX_REQ_DTOS * ISCSI_ISER_MAX_CONN) 43#define ISER_MAX_TX_LEN (ISER_QP_MAX_REQ_DTOS * ISCSI_ISER_MAX_CONN)
44#define ISER_MAX_CQ_LEN (ISER_MAX_RX_LEN + ISER_MAX_TX_LEN) 44#define ISER_MAX_CQ_LEN (ISER_MAX_RX_LEN + ISER_MAX_TX_LEN + \
45 ISCSI_ISER_MAX_CONN)
45 46
46static int iser_cq_poll_limit = 512; 47static int iser_cq_poll_limit = 512;
47 48
@@ -457,10 +458,10 @@ static int iser_create_ib_conn_res(struct ib_conn *ib_conn)
457 init_attr.sq_sig_type = IB_SIGNAL_REQ_WR; 458 init_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
458 init_attr.qp_type = IB_QPT_RC; 459 init_attr.qp_type = IB_QPT_RC;
459 if (ib_conn->pi_support) { 460 if (ib_conn->pi_support) {
460 init_attr.cap.max_send_wr = ISER_QP_SIG_MAX_REQ_DTOS; 461 init_attr.cap.max_send_wr = ISER_QP_SIG_MAX_REQ_DTOS + 1;
461 init_attr.create_flags |= IB_QP_CREATE_SIGNATURE_EN; 462 init_attr.create_flags |= IB_QP_CREATE_SIGNATURE_EN;
462 } else { 463 } else {
463 init_attr.cap.max_send_wr = ISER_QP_MAX_REQ_DTOS; 464 init_attr.cap.max_send_wr = ISER_QP_MAX_REQ_DTOS + 1;
464 } 465 }
465 466
466 ret = rdma_create_qp(ib_conn->cma_id, device->pd, &init_attr); 467 ret = rdma_create_qp(ib_conn->cma_id, device->pd, &init_attr);
@@ -634,6 +635,7 @@ void iser_conn_release(struct iser_conn *iser_conn)
634int iser_conn_terminate(struct iser_conn *iser_conn) 635int iser_conn_terminate(struct iser_conn *iser_conn)
635{ 636{
636 struct ib_conn *ib_conn = &iser_conn->ib_conn; 637 struct ib_conn *ib_conn = &iser_conn->ib_conn;
638 struct ib_send_wr *bad_wr;
637 int err = 0; 639 int err = 0;
638 640
639 /* terminate the iser conn only if the conn state is UP */ 641 /* terminate the iser conn only if the conn state is UP */
@@ -658,6 +660,11 @@ int iser_conn_terminate(struct iser_conn *iser_conn)
658 iser_err("Failed to disconnect, conn: 0x%p err %d\n", 660 iser_err("Failed to disconnect, conn: 0x%p err %d\n",
659 iser_conn, err); 661 iser_conn, err);
660 662
663 /* post an indication that all flush errors were consumed */
664 err = ib_post_send(ib_conn->qp, &ib_conn->beacon, &bad_wr);
665 if (err)
666 iser_err("conn %p failed to post beacon", ib_conn);
667
661 wait_for_completion(&ib_conn->flush_comp); 668 wait_for_completion(&ib_conn->flush_comp);
662 } 669 }
663 670
@@ -867,7 +874,6 @@ void iser_conn_init(struct iser_conn *iser_conn)
867{ 874{
868 iser_conn->state = ISER_CONN_INIT; 875 iser_conn->state = ISER_CONN_INIT;
869 iser_conn->ib_conn.post_recv_buf_count = 0; 876 iser_conn->ib_conn.post_recv_buf_count = 0;
870 atomic_set(&iser_conn->ib_conn.post_send_buf_count, 0);
871 init_completion(&iser_conn->ib_conn.flush_comp); 877 init_completion(&iser_conn->ib_conn.flush_comp);
872 init_completion(&iser_conn->stop_completion); 878 init_completion(&iser_conn->stop_completion);
873 init_completion(&iser_conn->ib_completion); 879 init_completion(&iser_conn->ib_completion);
@@ -900,6 +906,9 @@ int iser_connect(struct iser_conn *iser_conn,
900 906
901 iser_conn->state = ISER_CONN_PENDING; 907 iser_conn->state = ISER_CONN_PENDING;
902 908
909 ib_conn->beacon.wr_id = ISER_BEACON_WRID;
910 ib_conn->beacon.opcode = IB_WR_SEND;
911
903 ib_conn->cma_id = rdma_create_id(iser_cma_handler, 912 ib_conn->cma_id = rdma_create_id(iser_cma_handler,
904 (void *)iser_conn, 913 (void *)iser_conn,
905 RDMA_PS_TCP, IB_QPT_RC); 914 RDMA_PS_TCP, IB_QPT_RC);
@@ -1106,13 +1115,10 @@ int iser_post_send(struct ib_conn *ib_conn, struct iser_tx_desc *tx_desc)
1106 send_wr.opcode = IB_WR_SEND; 1115 send_wr.opcode = IB_WR_SEND;
1107 send_wr.send_flags = IB_SEND_SIGNALED; 1116 send_wr.send_flags = IB_SEND_SIGNALED;
1108 1117
1109 atomic_inc(&ib_conn->post_send_buf_count);
1110
1111 ib_ret = ib_post_send(ib_conn->qp, &send_wr, &send_wr_failed); 1118 ib_ret = ib_post_send(ib_conn->qp, &send_wr, &send_wr_failed);
1112 if (ib_ret) { 1119 if (ib_ret)
1113 iser_err("ib_post_send failed, ret:%d\n", ib_ret); 1120 iser_err("ib_post_send failed, ret:%d\n", ib_ret);
1114 atomic_dec(&ib_conn->post_send_buf_count); 1121
1115 }
1116 return ib_ret; 1122 return ib_ret;
1117} 1123}
1118 1124
@@ -1164,7 +1170,6 @@ iser_handle_comp_error(struct ib_conn *ib_conn,
1164 if (is_iser_tx_desc(iser_conn, (void *)wc->wr_id)) { 1170 if (is_iser_tx_desc(iser_conn, (void *)wc->wr_id)) {
1165 struct iser_tx_desc *desc = (struct iser_tx_desc *)wc->wr_id; 1171 struct iser_tx_desc *desc = (struct iser_tx_desc *)wc->wr_id;
1166 1172
1167 atomic_dec(&ib_conn->post_send_buf_count);
1168 if (desc->type == ISCSI_TX_DATAOUT) 1173 if (desc->type == ISCSI_TX_DATAOUT)
1169 kmem_cache_free(ig.desc_cache, desc); 1174 kmem_cache_free(ig.desc_cache, desc);
1170 } else { 1175 } else {
@@ -1196,7 +1201,6 @@ static void iser_handle_wc(struct ib_wc *wc)
1196 if (wc->opcode == IB_WC_SEND) { 1201 if (wc->opcode == IB_WC_SEND) {
1197 tx_desc = (struct iser_tx_desc *)wc->wr_id; 1202 tx_desc = (struct iser_tx_desc *)wc->wr_id;
1198 iser_snd_completion(tx_desc, ib_conn); 1203 iser_snd_completion(tx_desc, ib_conn);
1199 atomic_dec(&ib_conn->post_send_buf_count);
1200 } else { 1204 } else {
1201 iser_err("Unknown wc opcode %d\n", wc->opcode); 1205 iser_err("Unknown wc opcode %d\n", wc->opcode);
1202 } 1206 }
@@ -1207,12 +1211,12 @@ static void iser_handle_wc(struct ib_wc *wc)
1207 else 1211 else
1208 iser_dbg("flush error: wr id %llx\n", wc->wr_id); 1212 iser_dbg("flush error: wr id %llx\n", wc->wr_id);
1209 1213
1210 if (wc->wr_id != ISER_FASTREG_LI_WRID) 1214 if (wc->wr_id != ISER_FASTREG_LI_WRID &&
1215 wc->wr_id != ISER_BEACON_WRID)
1211 iser_handle_comp_error(ib_conn, wc); 1216 iser_handle_comp_error(ib_conn, wc);
1212 1217
1213 /* complete in case all flush errors were consumed */ 1218 /* complete in case all flush errors were consumed */
1214 if (ib_conn->post_recv_buf_count == 0 && 1219 if (wc->wr_id == ISER_BEACON_WRID)
1215 atomic_read(&ib_conn->post_send_buf_count) == 0)
1216 complete(&ib_conn->flush_comp); 1220 complete(&ib_conn->flush_comp);
1217 } 1221 }
1218} 1222}