aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2014-12-02 09:57:20 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-12-13 01:57:28 -0500
commit128e9cc84566a84146baea2335b3824288eed817 (patch)
tree16a38adc28b3a30337362fc69e576b81018c54f6 /drivers/infiniband
parent954f23722b5753305be490330cf2680b7a25f4a3 (diff)
iser-target: Fix flush + disconnect completion handling
ISER_CONN_UP state is not sufficient to know if we should wait for completion of flush errors and disconnected_handler event. Instead, split it to 2 states: - ISER_CONN_UP: Got to CM connected phase, This state indicates that we need to wait for a CM disconnect event before going to teardown. - ISER_CONN_FULL_FEATURE: Got to full feature phase after we posted login response, This state indicates that we posted recv buffers and we need to wait for flush completions before going to teardown. Also avoid deffering disconnected handler to a work, and handle it within disconnected handler. More work here is needed to handle DEVICE_REMOVAL event correctly (cleanup all resources). Squashed: iser-target: Don't deffer disconnected handler to a work Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Cc: <stable@vger.kernel.org> # v3.10+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c52
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.h2
2 files changed, 31 insertions, 23 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 2746bb857e57..bbc86110b477 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -756,6 +756,9 @@ isert_connected_handler(struct rdma_cm_id *cma_id)
756{ 756{
757 struct isert_conn *isert_conn = cma_id->context; 757 struct isert_conn *isert_conn = cma_id->context;
758 758
759 pr_info("conn %p\n", isert_conn);
760
761 isert_conn->state = ISER_CONN_UP;
759 kref_get(&isert_conn->conn_kref); 762 kref_get(&isert_conn->conn_kref);
760} 763}
761 764
@@ -782,8 +785,9 @@ isert_put_conn(struct isert_conn *isert_conn)
782 * @isert_conn: isert connection struct 785 * @isert_conn: isert connection struct
783 * 786 *
784 * Notes: 787 * Notes:
785 * In case the connection state is UP, move state 788 * In case the connection state is FULL_FEATURE, move state
786 * to TEMINATING and start teardown sequence (rdma_disconnect). 789 * to TEMINATING and start teardown sequence (rdma_disconnect).
790 * In case the connection state is UP, complete flush as well.
787 * 791 *
788 * This routine must be called with conn_mutex held. Thus it is 792 * This routine must be called with conn_mutex held. Thus it is
789 * safe to call multiple times. 793 * safe to call multiple times.
@@ -793,32 +797,31 @@ isert_conn_terminate(struct isert_conn *isert_conn)
793{ 797{
794 int err; 798 int err;
795 799
796 if (isert_conn->state == ISER_CONN_UP) { 800 switch (isert_conn->state) {
797 isert_conn->state = ISER_CONN_TERMINATING; 801 case ISER_CONN_TERMINATING:
802 break;
803 case ISER_CONN_UP:
804 /*
805 * No flush completions will occur as we didn't
806 * get to ISER_CONN_FULL_FEATURE yet, complete
807 * to allow teardown progress.
808 */
809 complete(&isert_conn->conn_wait_comp_err);
810 case ISER_CONN_FULL_FEATURE: /* FALLTHRU */
798 pr_info("Terminating conn %p state %d\n", 811 pr_info("Terminating conn %p state %d\n",
799 isert_conn, isert_conn->state); 812 isert_conn, isert_conn->state);
813 isert_conn->state = ISER_CONN_TERMINATING;
800 err = rdma_disconnect(isert_conn->conn_cm_id); 814 err = rdma_disconnect(isert_conn->conn_cm_id);
801 if (err) 815 if (err)
802 pr_warn("Failed rdma_disconnect isert_conn %p\n", 816 pr_warn("Failed rdma_disconnect isert_conn %p\n",
803 isert_conn); 817 isert_conn);
818 break;
819 default:
820 pr_warn("conn %p teminating in state %d\n",
821 isert_conn, isert_conn->state);
804 } 822 }
805} 823}
806 824
807static void
808isert_disconnect_work(struct work_struct *work)
809{
810 struct isert_conn *isert_conn = container_of(work,
811 struct isert_conn, conn_logout_work);
812
813 pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
814 mutex_lock(&isert_conn->conn_mutex);
815 isert_conn_terminate(isert_conn);
816 mutex_unlock(&isert_conn->conn_mutex);
817
818 pr_info("conn %p completing conn_wait\n", isert_conn);
819 complete(&isert_conn->conn_wait);
820}
821
822static int 825static int
823isert_disconnected_handler(struct rdma_cm_id *cma_id) 826isert_disconnected_handler(struct rdma_cm_id *cma_id)
824{ 827{
@@ -833,8 +836,12 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id)
833 836
834 isert_conn = (struct isert_conn *)cma_id->context; 837 isert_conn = (struct isert_conn *)cma_id->context;
835 838
836 INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work); 839 mutex_lock(&isert_conn->conn_mutex);
837 schedule_work(&isert_conn->conn_logout_work); 840 isert_conn_terminate(isert_conn);
841 mutex_unlock(&isert_conn->conn_mutex);
842
843 pr_info("conn %p completing conn_wait\n", isert_conn);
844 complete(&isert_conn->conn_wait);
838 845
839 return 0; 846 return 0;
840} 847}
@@ -1009,7 +1016,7 @@ isert_init_send_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
1009 * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls. 1016 * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls.
1010 */ 1017 */
1011 mutex_lock(&isert_conn->conn_mutex); 1018 mutex_lock(&isert_conn->conn_mutex);
1012 if (coalesce && isert_conn->state == ISER_CONN_UP && 1019 if (coalesce && isert_conn->state == ISER_CONN_FULL_FEATURE &&
1013 ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) { 1020 ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) {
1014 tx_desc->llnode_active = true; 1021 tx_desc->llnode_active = true;
1015 llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist); 1022 llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist);
@@ -1110,7 +1117,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
1110 if (ret) 1117 if (ret)
1111 return ret; 1118 return ret;
1112 1119
1113 isert_conn->state = ISER_CONN_UP; 1120 /* Now we are in FULL_FEATURE phase */
1121 isert_conn->state = ISER_CONN_FULL_FEATURE;
1114 goto post_send; 1122 goto post_send;
1115 } 1123 }
1116 1124
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h
index a2e926452f76..dd4e0bf9563a 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.h
+++ b/drivers/infiniband/ulp/isert/ib_isert.h
@@ -23,6 +23,7 @@ enum iser_ib_op_code {
23enum iser_conn_state { 23enum iser_conn_state {
24 ISER_CONN_INIT, 24 ISER_CONN_INIT,
25 ISER_CONN_UP, 25 ISER_CONN_UP,
26 ISER_CONN_FULL_FEATURE,
26 ISER_CONN_TERMINATING, 27 ISER_CONN_TERMINATING,
27 ISER_CONN_DOWN, 28 ISER_CONN_DOWN,
28}; 29};
@@ -138,7 +139,6 @@ struct isert_conn {
138 struct ib_mr *conn_mr; 139 struct ib_mr *conn_mr;
139 struct ib_qp *conn_qp; 140 struct ib_qp *conn_qp;
140 struct isert_device *conn_device; 141 struct isert_device *conn_device;
141 struct work_struct conn_logout_work;
142 struct mutex conn_mutex; 142 struct mutex conn_mutex;
143 struct completion conn_wait; 143 struct completion conn_wait;
144 struct completion conn_wait_comp_err; 144 struct completion conn_wait_comp_err;