OSDN Git Service

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
[uclinux-h8/linux.git] / drivers / infiniband / ulp / isert / ib_isert.c
index 9e7b492..f3b7a34 100644 (file)
@@ -65,6 +65,8 @@ static int
 isert_rdma_accept(struct isert_conn *isert_conn);
 struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);
 
+static void isert_release_work(struct work_struct *work);
+
 static inline bool
 isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd)
 {
@@ -552,11 +554,11 @@ isert_create_pi_ctx(struct fast_reg_descriptor *desc,
        return 0;
 
 err_prot_mr:
-       ib_dereg_mr(desc->pi_ctx->prot_mr);
+       ib_dereg_mr(pi_ctx->prot_mr);
 err_prot_frpl:
-       ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl);
+       ib_free_fast_reg_page_list(pi_ctx->prot_frpl);
 err_pi_ctx:
-       kfree(desc->pi_ctx);
+       kfree(pi_ctx);
 
        return ret;
 }
@@ -653,6 +655,7 @@ isert_init_conn(struct isert_conn *isert_conn)
        mutex_init(&isert_conn->mutex);
        spin_lock_init(&isert_conn->pool_lock);
        INIT_LIST_HEAD(&isert_conn->fr_pool);
+       INIT_WORK(&isert_conn->release_work, isert_release_work);
 }
 
 static void
@@ -931,6 +934,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
 {
        struct isert_np *isert_np = cma_id->context;
        struct isert_conn *isert_conn;
+       bool terminating = false;
 
        if (isert_np->np_cm_id == cma_id)
                return isert_np_cma_handler(cma_id->context, event);
@@ -938,12 +942,25 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
        isert_conn = cma_id->qp->qp_context;
 
        mutex_lock(&isert_conn->mutex);
+       terminating = (isert_conn->state == ISER_CONN_TERMINATING);
        isert_conn_terminate(isert_conn);
        mutex_unlock(&isert_conn->mutex);
 
        isert_info("conn %p completing wait\n", isert_conn);
        complete(&isert_conn->wait);
 
+       if (terminating)
+               goto out;
+
+       mutex_lock(&isert_np->np_accept_mutex);
+       if (!list_empty(&isert_conn->accept_node)) {
+               list_del_init(&isert_conn->accept_node);
+               isert_put_conn(isert_conn);
+               queue_work(isert_release_wq, &isert_conn->release_work);
+       }
+       mutex_unlock(&isert_np->np_accept_mutex);
+
+out:
        return 0;
 }
 
@@ -2390,7 +2407,6 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
        page_off = offset % PAGE_SIZE;
 
        send_wr->sg_list = ib_sge;
-       send_wr->num_sge = sg_nents;
        send_wr->wr_id = (uintptr_t)&isert_cmd->tx_desc;
        /*
         * Perform mapping of TCM scatterlist memory ib_sge dma_addr.
@@ -2410,14 +2426,17 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
                          ib_sge->addr, ib_sge->length, ib_sge->lkey);
                page_off = 0;
                data_left -= ib_sge->length;
+               if (!data_left)
+                       break;
                ib_sge++;
                isert_dbg("Incrementing ib_sge pointer to %p\n", ib_sge);
        }
 
+       send_wr->num_sge = ++i;
        isert_dbg("Set outgoing sg_list: %p num_sg: %u from TCM SGLs\n",
                  send_wr->sg_list, send_wr->num_sge);
 
-       return sg_nents;
+       return send_wr->num_sge;
 }
 
 static int
@@ -3376,7 +3395,6 @@ static void isert_wait_conn(struct iscsi_conn *conn)
        isert_wait4flush(isert_conn);
        isert_wait4logout(isert_conn);
 
-       INIT_WORK(&isert_conn->release_work, isert_release_work);
        queue_work(isert_release_wq, &isert_conn->release_work);
 }
 
@@ -3384,6 +3402,7 @@ static void isert_free_conn(struct iscsi_conn *conn)
 {
        struct isert_conn *isert_conn = conn->context;
 
+       isert_wait4flush(isert_conn);
        isert_put_conn(isert_conn);
 }