IB/iser: Replace connection waitqueue with completion object
[deliverable/linux.git] / drivers / infiniband / ulp / iser / iscsi_iser.c
index eb7973957a6ea35585a16086adc40e29df151cb9..61ee91d883806322f60c79eaae6ec1dde865ad54 100644 (file)
@@ -596,20 +596,28 @@ iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
        struct iser_conn *ib_conn;
        struct iscsi_endpoint *ep;
 
-       ep = iscsi_create_endpoint(sizeof(*ib_conn));
+       ep = iscsi_create_endpoint(0);
        if (!ep)
                return ERR_PTR(-ENOMEM);
 
-       ib_conn = ep->dd_data;
+       ib_conn = kzalloc(sizeof(*ib_conn), GFP_KERNEL);
+       if (!ib_conn) {
+               err = -ENOMEM;
+               goto failure;
+       }
+
+       ep->dd_data = ib_conn;
        ib_conn->ep = ep;
        iser_conn_init(ib_conn);
 
-       err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr,
-                          non_blocking);
+       err = iser_connect(ib_conn, NULL, dst_addr, non_blocking);
        if (err)
-               return ERR_PTR(err);
+               goto failure;
 
        return ep;
+failure:
+       iscsi_destroy_endpoint(ep);
+       return ERR_PTR(err);
 }
 
 static int
@@ -619,15 +627,16 @@ iscsi_iser_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
        int rc;
 
        ib_conn = ep->dd_data;
-       rc = wait_event_interruptible_timeout(ib_conn->wait,
-                            ib_conn->state == ISER_CONN_UP,
-                            msecs_to_jiffies(timeout_ms));
-
+       rc = wait_for_completion_interruptible_timeout(&ib_conn->up_completion,
+                                                      msecs_to_jiffies(timeout_ms));
        /* if conn establishment failed, return error code to iscsi */
-       if (!rc &&
-           (ib_conn->state == ISER_CONN_TERMINATING ||
-            ib_conn->state == ISER_CONN_DOWN))
-               rc = -1;
+       if (rc == 0) {
+               mutex_lock(&ib_conn->state_mutex);
+               if (ib_conn->state == ISER_CONN_TERMINATING ||
+                   ib_conn->state == ISER_CONN_DOWN)
+                       rc = -1;
+               mutex_unlock(&ib_conn->state_mutex);
+       }
 
        iser_info("ib conn %p rc = %d\n", ib_conn, rc);
 
@@ -646,19 +655,25 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
 
        ib_conn = ep->dd_data;
        iser_info("ep %p ib conn %p state %d\n", ep, ib_conn, ib_conn->state);
+       mutex_lock(&ib_conn->state_mutex);
        iser_conn_terminate(ib_conn);
 
        /*
-        * if iser_conn and iscsi_conn are bound, we must wait iscsi_conn_stop
-        * call and ISER_CONN_DOWN state before freeing the iser resources.
-        * otherwise we are safe to free resources immediately.
+        * if iser_conn and iscsi_conn are bound, we must wait for
+        * iscsi_conn_stop and flush errors completion before freeing
+        * the iser resources. Otherwise we are safe to free resources
+        * immediately.
         */
        if (ib_conn->iscsi_conn) {
                INIT_WORK(&ib_conn->release_work, iser_release_work);
                queue_work(release_wq, &ib_conn->release_work);
+               mutex_unlock(&ib_conn->state_mutex);
        } else {
+               ib_conn->state = ISER_CONN_DOWN;
+               mutex_unlock(&ib_conn->state_mutex);
                iser_conn_release(ib_conn);
        }
+       iscsi_destroy_endpoint(ep);
 }
 
 static umode_t iser_attr_is_visible(int param_type, int param)
This page took 0.026111 seconds and 5 git commands to generate.