aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorAriel Nahum <arieln@mellanox.com>2014-07-31 06:27:50 -0400
committerRoland Dreier <roland@purestorage.com>2014-08-01 18:10:05 -0400
commit9a6d3234a192d4a3a51df1042c13af13f996242a (patch)
treea5c1c408abffe9c89c5d94b5c8cff6ae18844713 /drivers/infiniband
parent504130c039f917aba8b145fe8ea99be95e662fca (diff)
IB/iser: Replace connection waitqueue with completion object
Instead of waiting for events and condition changes of the iser connection state, we wait for explicit completion of connection establishment and teardown. Separate connection establishment wait object from the teardown object to avoid a situation where racing connection establishment and teardown may concurrently wakeup each other. ep_poll will wait for up_completion invoked by iser_connected_handler() and iser release worker will wait for flush_completion before releasing the connection. Bound the completion wait with a 30 seconds timeout for cases where iscsid (the user space iscsi daemon) is too slow or gone. Signed-off-by: Ariel Nahum <arieln@mellanox.com> Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c13
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h3
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c29
3 files changed, 22 insertions, 23 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 3dc853c9e4bf..61ee91d88380 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -627,10 +627,8 @@ iscsi_iser_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
627 int rc; 627 int rc;
628 628
629 ib_conn = ep->dd_data; 629 ib_conn = ep->dd_data;
630 rc = wait_event_interruptible_timeout(ib_conn->wait, 630 rc = wait_for_completion_interruptible_timeout(&ib_conn->up_completion,
631 ib_conn->state == ISER_CONN_UP, 631 msecs_to_jiffies(timeout_ms));
632 msecs_to_jiffies(timeout_ms));
633
634 /* if conn establishment failed, return error code to iscsi */ 632 /* if conn establishment failed, return error code to iscsi */
635 if (rc == 0) { 633 if (rc == 0) {
636 mutex_lock(&ib_conn->state_mutex); 634 mutex_lock(&ib_conn->state_mutex);
@@ -661,9 +659,10 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
661 iser_conn_terminate(ib_conn); 659 iser_conn_terminate(ib_conn);
662 660
663 /* 661 /*
664 * if iser_conn and iscsi_conn are bound, we must wait iscsi_conn_stop 662 * if iser_conn and iscsi_conn are bound, we must wait for
665 * call and ISER_CONN_DOWN state before freeing the iser resources. 663 * iscsi_conn_stop and flush errors completion before freeing
666 * otherwise we are safe to free resources immediately. 664 * the iser resources. Otherwise we are safe to free resources
665 * immediately.
667 */ 666 */
668 if (ib_conn->iscsi_conn) { 667 if (ib_conn->iscsi_conn) {
669 INIT_WORK(&ib_conn->release_work, iser_release_work); 668 INIT_WORK(&ib_conn->release_work, iser_release_work);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index c7efc5a91604..c877dad381cb 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -326,7 +326,6 @@ struct iser_conn {
326 struct iser_device *device; /* device context */ 326 struct iser_device *device; /* device context */
327 struct rdma_cm_id *cma_id; /* CMA ID */ 327 struct rdma_cm_id *cma_id; /* CMA ID */
328 struct ib_qp *qp; /* QP */ 328 struct ib_qp *qp; /* QP */
329 wait_queue_head_t wait; /* waitq for conn/disconn */
330 unsigned qp_max_recv_dtos; /* num of rx buffers */ 329 unsigned qp_max_recv_dtos; /* num of rx buffers */
331 unsigned qp_max_recv_dtos_mask; /* above minus 1 */ 330 unsigned qp_max_recv_dtos_mask; /* above minus 1 */
332 unsigned min_posted_rx; /* qp_max_recv_dtos >> 2 */ 331 unsigned min_posted_rx; /* qp_max_recv_dtos >> 2 */
@@ -336,6 +335,8 @@ struct iser_conn {
336 struct work_struct release_work; 335 struct work_struct release_work;
337 struct completion stop_completion; 336 struct completion stop_completion;
338 struct mutex state_mutex; 337 struct mutex state_mutex;
338 struct completion flush_completion;
339 struct completion up_completion;
339 struct list_head conn_list; /* entry in ig conn list */ 340 struct list_head conn_list; /* entry in ig conn list */
340 341
341 char *login_buf; 342 char *login_buf;
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 6e7e54d883ab..06a49b3df3fd 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -582,15 +582,19 @@ static int iser_conn_state_comp_exch(struct iser_conn *ib_conn,
582void iser_release_work(struct work_struct *work) 582void iser_release_work(struct work_struct *work)
583{ 583{
584 struct iser_conn *ib_conn; 584 struct iser_conn *ib_conn;
585 int rc;
585 586
586 ib_conn = container_of(work, struct iser_conn, release_work); 587 ib_conn = container_of(work, struct iser_conn, release_work);
587 588
588 /* wait for .conn_stop callback */ 589 /* wait for .conn_stop callback */
589 wait_for_completion(&ib_conn->stop_completion); 590 rc = wait_for_completion_timeout(&ib_conn->stop_completion, 30 * HZ);
591 WARN_ON(rc == 0);
590 592
591 /* wait for the qp`s post send and post receive buffers to empty */ 593 /* wait for the qp`s post send and post receive buffers to empty */
592 wait_event_interruptible(ib_conn->wait, 594 rc = wait_for_completion_timeout(&ib_conn->flush_completion, 30 * HZ);
593 ib_conn->state == ISER_CONN_DOWN); 595 WARN_ON(rc == 0);
596
597 ib_conn->state = ISER_CONN_DOWN;
594 598
595 mutex_lock(&ib_conn->state_mutex); 599 mutex_lock(&ib_conn->state_mutex);
596 ib_conn->state = ISER_CONN_DOWN; 600 ib_conn->state = ISER_CONN_DOWN;
@@ -656,9 +660,7 @@ static void iser_connect_error(struct rdma_cm_id *cma_id)
656 struct iser_conn *ib_conn; 660 struct iser_conn *ib_conn;
657 661
658 ib_conn = (struct iser_conn *)cma_id->context; 662 ib_conn = (struct iser_conn *)cma_id->context;
659
660 ib_conn->state = ISER_CONN_DOWN; 663 ib_conn->state = ISER_CONN_DOWN;
661 wake_up_interruptible(&ib_conn->wait);
662} 664}
663 665
664/** 666/**
@@ -761,9 +763,8 @@ static void iser_connected_handler(struct rdma_cm_id *cma_id)
761 (void)ib_query_qp(cma_id->qp, &attr, ~0, &init_attr); 763 (void)ib_query_qp(cma_id->qp, &attr, ~0, &init_attr);
762 iser_info("remote qpn:%x my qpn:%x\n", attr.dest_qp_num, cma_id->qp->qp_num); 764 iser_info("remote qpn:%x my qpn:%x\n", attr.dest_qp_num, cma_id->qp->qp_num);
763 765
764 ib_conn = (struct iser_conn *)cma_id->context; 766 ib_conn->state = ISER_CONN_UP;
765 if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_PENDING, ISER_CONN_UP)) 767 complete(&ib_conn->up_completion);
766 wake_up_interruptible(&ib_conn->wait);
767} 768}
768 769
769static void iser_disconnected_handler(struct rdma_cm_id *cma_id) 770static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
@@ -785,8 +786,7 @@ static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
785 /* Complete the termination process if no posts are pending */ 786 /* Complete the termination process if no posts are pending */
786 if (ib_conn->post_recv_buf_count == 0 && 787 if (ib_conn->post_recv_buf_count == 0 &&
787 (atomic_read(&ib_conn->post_send_buf_count) == 0)) { 788 (atomic_read(&ib_conn->post_send_buf_count) == 0)) {
788 ib_conn->state = ISER_CONN_DOWN; 789 complete(&ib_conn->flush_completion);
789 wake_up_interruptible(&ib_conn->wait);
790 } 790 }
791} 791}
792 792
@@ -833,10 +833,11 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
833void iser_conn_init(struct iser_conn *ib_conn) 833void iser_conn_init(struct iser_conn *ib_conn)
834{ 834{
835 ib_conn->state = ISER_CONN_INIT; 835 ib_conn->state = ISER_CONN_INIT;
836 init_waitqueue_head(&ib_conn->wait);
837 ib_conn->post_recv_buf_count = 0; 836 ib_conn->post_recv_buf_count = 0;
838 atomic_set(&ib_conn->post_send_buf_count, 0); 837 atomic_set(&ib_conn->post_send_buf_count, 0);
839 init_completion(&ib_conn->stop_completion); 838 init_completion(&ib_conn->stop_completion);
839 init_completion(&ib_conn->flush_completion);
840 init_completion(&ib_conn->up_completion);
840 INIT_LIST_HEAD(&ib_conn->conn_list); 841 INIT_LIST_HEAD(&ib_conn->conn_list);
841 spin_lock_init(&ib_conn->lock); 842 spin_lock_init(&ib_conn->lock);
842 mutex_init(&ib_conn->state_mutex); 843 mutex_init(&ib_conn->state_mutex);
@@ -880,8 +881,7 @@ int iser_connect(struct iser_conn *ib_conn,
880 } 881 }
881 882
882 if (!non_blocking) { 883 if (!non_blocking) {
883 wait_event_interruptible(ib_conn->wait, 884 wait_for_completion_interruptible(&ib_conn->up_completion);
884 (ib_conn->state != ISER_CONN_PENDING));
885 885
886 if (ib_conn->state != ISER_CONN_UP) { 886 if (ib_conn->state != ISER_CONN_UP) {
887 err = -EIO; 887 err = -EIO;
@@ -1097,8 +1097,7 @@ static void iser_handle_comp_error(struct iser_tx_desc *desc,
1097 1097
1098 /* no more non completed posts to the QP, complete the 1098 /* no more non completed posts to the QP, complete the
1099 * termination process w.o worrying on disconnect event */ 1099 * termination process w.o worrying on disconnect event */
1100 ib_conn->state = ISER_CONN_DOWN; 1100 complete(&ib_conn->flush_completion);
1101 wake_up_interruptible(&ib_conn->wait);
1102 } 1101 }
1103} 1102}
1104 1103