These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / infiniband / ulp / isert / ib_isert.c
index 575a072..8a51c3b 100644 (file)
@@ -80,7 +80,9 @@ isert_qp_event_callback(struct ib_event *e, void *context)
 {
        struct isert_conn *isert_conn = context;
 
-       isert_err("conn %p event: %d\n", isert_conn, e->event);
+       isert_err("%s (%d): conn %p\n",
+                 ib_event_msg(e->event), e->event, isert_conn);
+
        switch (e->event) {
        case IB_EVENT_COMM_EST:
                rdma_notify(isert_conn->cm_id, IB_EVENT_COMM_EST);
@@ -155,16 +157,9 @@ isert_create_qp(struct isert_conn *isert_conn,
        attr.recv_cq = comp->cq;
        attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS;
        attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS + 1;
-       /*
-        * FIXME: Use devattr.max_sge - 2 for max_send_sge as
-        * work-around for RDMA_READs with ConnectX-2.
-        *
-        * Also, still make sure to have at least two SGEs for
-        * outgoing control PDU responses.
-        */
-       attr.cap.max_send_sge = max(2, device->dev_attr.max_sge - 2);
-       isert_conn->max_sge = attr.cap.max_send_sge;
-
+       attr.cap.max_send_sge = device->dev_attr.max_sge;
+       isert_conn->max_sge = min(device->dev_attr.max_sge,
+                                 device->dev_attr.max_sge_rd);
        attr.cap.max_recv_sge = 1;
        attr.sq_sig_type = IB_SIGNAL_REQ_WR;
        attr.qp_type = IB_QPT_RC;
@@ -233,11 +228,9 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
                rx_sg = &rx_desc->rx_sg;
                rx_sg->addr = rx_desc->dma_addr;
                rx_sg->length = ISER_RX_PAYLOAD_SIZE;
-               rx_sg->lkey = device->mr->lkey;
+               rx_sg->lkey = device->pd->local_dma_lkey;
        }
 
-       isert_conn->rx_desc_head = 0;
-
        return 0;
 
 dma_map_fail:
@@ -318,15 +311,18 @@ isert_alloc_comps(struct isert_device *device,
        max_cqe = min(ISER_MAX_CQ_LEN, attr->max_cqe);
 
        for (i = 0; i < device->comps_used; i++) {
+               struct ib_cq_init_attr cq_attr = {};
                struct isert_comp *comp = &device->comps[i];
 
                comp->device = device;
                INIT_WORK(&comp->work, isert_cq_work);
+               cq_attr.cqe = max_cqe;
+               cq_attr.comp_vector = i;
                comp->cq = ib_create_cq(device->ib_device,
                                        isert_cq_callback,
                                        isert_cq_event_callback,
                                        (void *)comp,
-                                       max_cqe, i);
+                                       &cq_attr);
                if (IS_ERR(comp->cq)) {
                        isert_err("Unable to allocate cq\n");
                        ret = PTR_ERR(comp->cq);
@@ -380,22 +376,12 @@ isert_create_device_ib_res(struct isert_device *device)
                goto out_cq;
        }
 
-       device->mr = ib_get_dma_mr(device->pd, IB_ACCESS_LOCAL_WRITE);
-       if (IS_ERR(device->mr)) {
-               ret = PTR_ERR(device->mr);
-               isert_err("failed to create dma mr, device %p, ret=%d\n",
-                         device, ret);
-               goto out_mr;
-       }
-
        /* Check signature cap */
        device->pi_capable = dev_attr->device_cap_flags &
                             IB_DEVICE_SIGNATURE_HANDOVER ? true : false;
 
        return 0;
 
-out_mr:
-       ib_dealloc_pd(device->pd);
 out_cq:
        isert_free_comps(device);
        return ret;
@@ -406,7 +392,6 @@ isert_free_device_ib_res(struct isert_device *device)
 {
        isert_info("device %p\n", device);
 
-       ib_dereg_mr(device->mr);
        ib_dealloc_pd(device->pd);
        isert_free_comps(device);
 }
@@ -481,12 +466,10 @@ isert_conn_free_fastreg_pool(struct isert_conn *isert_conn)
        list_for_each_entry_safe(fr_desc, tmp,
                                 &isert_conn->fr_pool, list) {
                list_del(&fr_desc->list);
-               ib_free_fast_reg_page_list(fr_desc->data_frpl);
                ib_dereg_mr(fr_desc->data_mr);
                if (fr_desc->pi_ctx) {
-                       ib_free_fast_reg_page_list(fr_desc->pi_ctx->prot_frpl);
                        ib_dereg_mr(fr_desc->pi_ctx->prot_mr);
-                       ib_destroy_mr(fr_desc->pi_ctx->sig_mr);
+                       ib_dereg_mr(fr_desc->pi_ctx->sig_mr);
                        kfree(fr_desc->pi_ctx);
                }
                kfree(fr_desc);
@@ -503,7 +486,6 @@ isert_create_pi_ctx(struct fast_reg_descriptor *desc,
                    struct ib_device *device,
                    struct ib_pd *pd)
 {
-       struct ib_mr_init_attr mr_init_attr;
        struct pi_context *pi_ctx;
        int ret;
 
@@ -513,28 +495,17 @@ isert_create_pi_ctx(struct fast_reg_descriptor *desc,
                return -ENOMEM;
        }
 
-       pi_ctx->prot_frpl = ib_alloc_fast_reg_page_list(device,
-                                           ISCSI_ISER_SG_TABLESIZE);
-       if (IS_ERR(pi_ctx->prot_frpl)) {
-               isert_err("Failed to allocate prot frpl err=%ld\n",
-                         PTR_ERR(pi_ctx->prot_frpl));
-               ret = PTR_ERR(pi_ctx->prot_frpl);
-               goto err_pi_ctx;
-       }
-
-       pi_ctx->prot_mr = ib_alloc_fast_reg_mr(pd, ISCSI_ISER_SG_TABLESIZE);
+       pi_ctx->prot_mr = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG,
+                                     ISCSI_ISER_SG_TABLESIZE);
        if (IS_ERR(pi_ctx->prot_mr)) {
                isert_err("Failed to allocate prot frmr err=%ld\n",
                          PTR_ERR(pi_ctx->prot_mr));
                ret = PTR_ERR(pi_ctx->prot_mr);
-               goto err_prot_frpl;
+               goto err_pi_ctx;
        }
        desc->ind |= ISERT_PROT_KEY_VALID;
 
-       memset(&mr_init_attr, 0, sizeof(mr_init_attr));
-       mr_init_attr.max_reg_descriptors = 2;
-       mr_init_attr.flags |= IB_MR_SIGNATURE_EN;
-       pi_ctx->sig_mr = ib_create_mr(pd, &mr_init_attr);
+       pi_ctx->sig_mr = ib_alloc_mr(pd, IB_MR_TYPE_SIGNATURE, 2);
        if (IS_ERR(pi_ctx->sig_mr)) {
                isert_err("Failed to allocate signature enabled mr err=%ld\n",
                          PTR_ERR(pi_ctx->sig_mr));
@@ -550,8 +521,6 @@ isert_create_pi_ctx(struct fast_reg_descriptor *desc,
 
 err_prot_mr:
        ib_dereg_mr(pi_ctx->prot_mr);
-err_prot_frpl:
-       ib_free_fast_reg_page_list(pi_ctx->prot_frpl);
 err_pi_ctx:
        kfree(pi_ctx);
 
@@ -562,33 +531,18 @@ static int
 isert_create_fr_desc(struct ib_device *ib_device, struct ib_pd *pd,
                     struct fast_reg_descriptor *fr_desc)
 {
-       int ret;
-
-       fr_desc->data_frpl = ib_alloc_fast_reg_page_list(ib_device,
-                                                        ISCSI_ISER_SG_TABLESIZE);
-       if (IS_ERR(fr_desc->data_frpl)) {
-               isert_err("Failed to allocate data frpl err=%ld\n",
-                         PTR_ERR(fr_desc->data_frpl));
-               return PTR_ERR(fr_desc->data_frpl);
-       }
-
-       fr_desc->data_mr = ib_alloc_fast_reg_mr(pd, ISCSI_ISER_SG_TABLESIZE);
+       fr_desc->data_mr = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG,
+                                      ISCSI_ISER_SG_TABLESIZE);
        if (IS_ERR(fr_desc->data_mr)) {
                isert_err("Failed to allocate data frmr err=%ld\n",
                          PTR_ERR(fr_desc->data_mr));
-               ret = PTR_ERR(fr_desc->data_mr);
-               goto err_data_frpl;
+               return PTR_ERR(fr_desc->data_mr);
        }
        fr_desc->ind |= ISERT_DATA_KEY_VALID;
 
        isert_dbg("Created fr_desc %p\n", fr_desc);
 
        return 0;
-
-err_data_frpl:
-       ib_free_fast_reg_page_list(fr_desc->data_frpl);
-
-       return ret;
 }
 
 static int
@@ -642,7 +596,7 @@ static void
 isert_init_conn(struct isert_conn *isert_conn)
 {
        isert_conn->state = ISER_CONN_INIT;
-       INIT_LIST_HEAD(&isert_conn->accept_node);
+       INIT_LIST_HEAD(&isert_conn->node);
        init_completion(&isert_conn->login_comp);
        init_completion(&isert_conn->login_req_comp);
        init_completion(&isert_conn->wait);
@@ -775,12 +729,10 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        if (ret)
                goto out_conn_dev;
 
-       mutex_lock(&isert_np->np_accept_mutex);
-       list_add_tail(&isert_conn->accept_node, &isert_np->np_accept_list);
-       mutex_unlock(&isert_np->np_accept_mutex);
+       mutex_lock(&isert_np->mutex);
+       list_add_tail(&isert_conn->node, &isert_np->accepted);
+       mutex_unlock(&isert_np->mutex);
 
-       isert_info("np %p: Allow accept_np to continue\n", np);
-       up(&isert_np->np_sem);
        return 0;
 
 out_conn_dev:
@@ -828,18 +780,21 @@ static void
 isert_connected_handler(struct rdma_cm_id *cma_id)
 {
        struct isert_conn *isert_conn = cma_id->qp->qp_context;
+       struct isert_np *isert_np = cma_id->context;
 
        isert_info("conn %p\n", isert_conn);
 
-       if (!kref_get_unless_zero(&isert_conn->kref)) {
-               isert_warn("conn %p connect_release is running\n", isert_conn);
-               return;
-       }
-
        mutex_lock(&isert_conn->mutex);
-       if (isert_conn->state != ISER_CONN_FULL_FEATURE)
-               isert_conn->state = ISER_CONN_UP;
+       isert_conn->state = ISER_CONN_UP;
+       kref_get(&isert_conn->kref);
        mutex_unlock(&isert_conn->mutex);
+
+       mutex_lock(&isert_np->mutex);
+       list_move_tail(&isert_conn->node, &isert_np->pending);
+       mutex_unlock(&isert_np->mutex);
+
+       isert_info("np %p: Allow accept_np to continue\n", isert_np);
+       up(&isert_np->sem);
 }
 
 static void
@@ -900,18 +855,19 @@ static int
 isert_np_cma_handler(struct isert_np *isert_np,
                     enum rdma_cm_event_type event)
 {
-       isert_dbg("isert np %p, handling event %d\n", isert_np, event);
+       isert_dbg("%s (%d): isert np %p\n",
+                 rdma_event_msg(event), event, isert_np);
 
        switch (event) {
        case RDMA_CM_EVENT_DEVICE_REMOVAL:
-               isert_np->np_cm_id = NULL;
+               isert_np->cm_id = NULL;
                break;
        case RDMA_CM_EVENT_ADDR_CHANGE:
-               isert_np->np_cm_id = isert_setup_id(isert_np);
-               if (IS_ERR(isert_np->np_cm_id)) {
+               isert_np->cm_id = isert_setup_id(isert_np);
+               if (IS_ERR(isert_np->cm_id)) {
                        isert_err("isert np %p setup id failed: %ld\n",
-                                 isert_np, PTR_ERR(isert_np->np_cm_id));
-                       isert_np->np_cm_id = NULL;
+                                 isert_np, PTR_ERR(isert_np->cm_id));
+                       isert_np->cm_id = NULL;
                }
                break;
        default:
@@ -930,7 +886,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
        struct isert_conn *isert_conn;
        bool terminating = false;
 
-       if (isert_np->np_cm_id == cma_id)
+       if (isert_np->cm_id == cma_id)
                return isert_np_cma_handler(cma_id->context, event);
 
        isert_conn = cma_id->qp->qp_context;
@@ -946,13 +902,13 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
        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);
+       mutex_lock(&isert_np->mutex);
+       if (!list_empty(&isert_conn->node)) {
+               list_del_init(&isert_conn->node);
                isert_put_conn(isert_conn);
                queue_work(isert_release_wq, &isert_conn->release_work);
        }
-       mutex_unlock(&isert_np->np_accept_mutex);
+       mutex_unlock(&isert_np->mutex);
 
 out:
        return 0;
@@ -963,6 +919,7 @@ isert_connect_error(struct rdma_cm_id *cma_id)
 {
        struct isert_conn *isert_conn = cma_id->qp->qp_context;
 
+       list_del_init(&isert_conn->node);
        isert_conn->cm_id = NULL;
        isert_put_conn(isert_conn);
 
@@ -974,7 +931,8 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
 {
        int ret = 0;
 
-       isert_info("event %d status %d id %p np %p\n", event->event,
+       isert_info("%s (%d): status %d id %p np %p\n",
+                  rdma_event_msg(event->event), event->event,
                   event->status, cma_id, cma_id->context);
 
        switch (event->event) {
@@ -1006,35 +964,51 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
 }
 
 static int
-isert_post_recv(struct isert_conn *isert_conn, u32 count)
+isert_post_recvm(struct isert_conn *isert_conn, u32 count)
 {
        struct ib_recv_wr *rx_wr, *rx_wr_failed;
        int i, ret;
-       unsigned int rx_head = isert_conn->rx_desc_head;
        struct iser_rx_desc *rx_desc;
 
        for (rx_wr = isert_conn->rx_wr, i = 0; i < count; i++, rx_wr++) {
-               rx_desc         = &isert_conn->rx_descs[rx_head];
-               rx_wr->wr_id    = (uintptr_t)rx_desc;
-               rx_wr->sg_list  = &rx_desc->rx_sg;
-               rx_wr->num_sge  = 1;
-               rx_wr->next     = rx_wr + 1;
-               rx_head = (rx_head + 1) & (ISERT_QP_MAX_RECV_DTOS - 1);
+               rx_desc = &isert_conn->rx_descs[i];
+               rx_wr->wr_id = (uintptr_t)rx_desc;
+               rx_wr->sg_list = &rx_desc->rx_sg;
+               rx_wr->num_sge = 1;
+               rx_wr->next = rx_wr + 1;
        }
-
        rx_wr--;
        rx_wr->next = NULL; /* mark end of work requests list */
 
        isert_conn->post_recv_buf_count += count;
        ret = ib_post_recv(isert_conn->qp, isert_conn->rx_wr,
-                               &rx_wr_failed);
+                          &rx_wr_failed);
        if (ret) {
                isert_err("ib_post_recv() failed with ret: %d\n", ret);
                isert_conn->post_recv_buf_count -= count;
-       } else {
-               isert_dbg("Posted %d RX buffers\n", count);
-               isert_conn->rx_desc_head = rx_head;
        }
+
+       return ret;
+}
+
+static int
+isert_post_recv(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc)
+{
+       struct ib_recv_wr *rx_wr_failed, rx_wr;
+       int ret;
+
+       rx_wr.wr_id = (uintptr_t)rx_desc;
+       rx_wr.sg_list = &rx_desc->rx_sg;
+       rx_wr.num_sge = 1;
+       rx_wr.next = NULL;
+
+       isert_conn->post_recv_buf_count++;
+       ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_failed);
+       if (ret) {
+               isert_err("ib_post_recv() failed with ret: %d\n", ret);
+               isert_conn->post_recv_buf_count--;
+       }
+
        return ret;
 }
 
@@ -1079,8 +1053,8 @@ isert_create_send_desc(struct isert_conn *isert_conn,
        tx_desc->num_sge = 1;
        tx_desc->isert_cmd = isert_cmd;
 
-       if (tx_desc->tx_sg[0].lkey != device->mr->lkey) {
-               tx_desc->tx_sg[0].lkey = device->mr->lkey;
+       if (tx_desc->tx_sg[0].lkey != device->pd->local_dma_lkey) {
+               tx_desc->tx_sg[0].lkey = device->pd->local_dma_lkey;
                isert_dbg("tx_desc %p lkey mismatch, fixing\n", tx_desc);
        }
 }
@@ -1103,7 +1077,7 @@ isert_init_tx_hdrs(struct isert_conn *isert_conn,
        tx_desc->dma_addr = dma_addr;
        tx_desc->tx_sg[0].addr  = tx_desc->dma_addr;
        tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
-       tx_desc->tx_sg[0].lkey = device->mr->lkey;
+       tx_desc->tx_sg[0].lkey = device->pd->local_dma_lkey;
 
        isert_dbg("Setup tx_sg[0].addr: 0x%llx length: %u lkey: 0x%x\n",
                  tx_desc->tx_sg[0].addr, tx_desc->tx_sg[0].length,
@@ -1136,7 +1110,7 @@ isert_rdma_post_recvl(struct isert_conn *isert_conn)
        memset(&sge, 0, sizeof(struct ib_sge));
        sge.addr = isert_conn->login_req_dma;
        sge.length = ISER_RX_LOGIN_SIZE;
-       sge.lkey = isert_conn->device->mr->lkey;
+       sge.lkey = isert_conn->device->pd->local_dma_lkey;
 
        isert_dbg("Setup sge: addr: %llx length: %d 0x%08x\n",
                sge.addr, sge.length, sge.lkey);
@@ -1186,7 +1160,7 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
 
                tx_dsg->addr    = isert_conn->login_rsp_dma;
                tx_dsg->length  = length;
-               tx_dsg->lkey    = isert_conn->device->mr->lkey;
+               tx_dsg->lkey    = isert_conn->device->pd->local_dma_lkey;
                tx_desc->num_sge = 2;
        }
        if (!login->login_failed) {
@@ -1205,7 +1179,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
                        if (ret)
                                return ret;
 
-                       ret = isert_post_recv(isert_conn, ISERT_MIN_POSTED_RX);
+                       ret = isert_post_recvm(isert_conn,
+                                              ISERT_QP_MAX_RECV_DTOS);
                        if (ret)
                                return ret;
 
@@ -1278,7 +1253,7 @@ isert_rx_login_req(struct isert_conn *isert_conn)
 }
 
 static struct iscsi_cmd
-*isert_allocate_cmd(struct iscsi_conn *conn)
+*isert_allocate_cmd(struct iscsi_conn *conn, struct iser_rx_desc *rx_desc)
 {
        struct isert_conn *isert_conn = conn->context;
        struct isert_cmd *isert_cmd;
@@ -1292,6 +1267,7 @@ static struct iscsi_cmd
        isert_cmd = iscsit_priv_cmd(cmd);
        isert_cmd->conn = isert_conn;
        isert_cmd->iscsi_cmd = cmd;
+       isert_cmd->rx_desc = rx_desc;
 
        return cmd;
 }
@@ -1303,9 +1279,9 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
 {
        struct iscsi_conn *conn = isert_conn->conn;
        struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
-       struct scatterlist *sg;
        int imm_data, imm_data_len, unsol_data, sg_nents, rc;
        bool dump_payload = false;
+       unsigned int data_len;
 
        rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
        if (rc < 0)
@@ -1314,7 +1290,10 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
        imm_data = cmd->immediate_data;
        imm_data_len = cmd->first_burst_len;
        unsol_data = cmd->unsolicited_data;
+       data_len = cmd->se_cmd.data_length;
 
+       if (imm_data && imm_data_len == data_len)
+               cmd->se_cmd.se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
        rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
        if (rc < 0) {
                return 0;
@@ -1326,13 +1305,20 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
        if (!imm_data)
                return 0;
 
-       sg = &cmd->se_cmd.t_data_sg[0];
-       sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
-
-       isert_dbg("Copying Immediate SG: %p sg_nents: %u from %p imm_data_len: %d\n",
-                 sg, sg_nents, &rx_desc->data[0], imm_data_len);
-
-       sg_copy_from_buffer(sg, sg_nents, &rx_desc->data[0], imm_data_len);
+       if (imm_data_len != data_len) {
+               sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
+               sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
+                                   &rx_desc->data[0], imm_data_len);
+               isert_dbg("Copy Immediate sg_nents: %u imm_data_len: %d\n",
+                         sg_nents, imm_data_len);
+       } else {
+               sg_init_table(&isert_cmd->sg, 1);
+               cmd->se_cmd.t_data_sg = &isert_cmd->sg;
+               cmd->se_cmd.t_data_nents = 1;
+               sg_set_buf(&isert_cmd->sg, &rx_desc->data[0], imm_data_len);
+               isert_dbg("Transfer Immediate imm_data_len: %d\n",
+                         imm_data_len);
+       }
 
        cmd->write_data_done += imm_data_len;
 
@@ -1349,7 +1335,7 @@ sequence_cmd:
        if (!rc && dump_payload == false && unsol_data)
                iscsit_set_unsoliticed_dataout(cmd);
        else if (dump_payload && imm_data)
-               target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
+               target_put_sess_cmd(&cmd->se_cmd);
 
        return 0;
 }
@@ -1407,6 +1393,15 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn,
        if (rc < 0)
                return rc;
 
+       /*
+        * multiple data-outs on the same command can arrive -
+        * so post the buffer before hand
+        */
+       rc = isert_post_recv(isert_conn, rx_desc);
+       if (rc) {
+               isert_err("ib_post_recv failed with %d\n", rc);
+               return rc;
+       }
        return 0;
 }
 
@@ -1479,7 +1474,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
 
        switch (opcode) {
        case ISCSI_OP_SCSI_CMD:
-               cmd = isert_allocate_cmd(conn);
+               cmd = isert_allocate_cmd(conn, rx_desc);
                if (!cmd)
                        break;
 
@@ -1493,7 +1488,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                                        rx_desc, (unsigned char *)hdr);
                break;
        case ISCSI_OP_NOOP_OUT:
-               cmd = isert_allocate_cmd(conn);
+               cmd = isert_allocate_cmd(conn, rx_desc);
                if (!cmd)
                        break;
 
@@ -1506,7 +1501,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                                                (unsigned char *)hdr);
                break;
        case ISCSI_OP_SCSI_TMFUNC:
-               cmd = isert_allocate_cmd(conn);
+               cmd = isert_allocate_cmd(conn, rx_desc);
                if (!cmd)
                        break;
 
@@ -1514,22 +1509,20 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                                                (unsigned char *)hdr);
                break;
        case ISCSI_OP_LOGOUT:
-               cmd = isert_allocate_cmd(conn);
+               cmd = isert_allocate_cmd(conn, rx_desc);
                if (!cmd)
                        break;
 
                ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr);
                break;
        case ISCSI_OP_TEXT:
-               if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF) {
+               if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF)
                        cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
-                       if (!cmd)
-                               break;
-               } else {
-                       cmd = isert_allocate_cmd(conn);
-                       if (!cmd)
-                               break;
-               }
+               else
+                       cmd = isert_allocate_cmd(conn, rx_desc);
+
+               if (!cmd)
+                       break;
 
                isert_cmd = iscsit_priv_cmd(cmd);
                ret = isert_handle_text_cmd(isert_conn, isert_cmd, cmd,
@@ -1550,7 +1543,6 @@ isert_rx_do_work(struct iser_rx_desc *rx_desc, struct isert_conn *isert_conn)
        struct iser_hdr *iser_hdr = &rx_desc->iser_header;
        uint64_t read_va = 0, write_va = 0;
        uint32_t read_stag = 0, write_stag = 0;
-       int rc;
 
        switch (iser_hdr->flags & 0xF0) {
        case ISCSI_CTRL:
@@ -1577,8 +1569,8 @@ isert_rx_do_work(struct iser_rx_desc *rx_desc, struct isert_conn *isert_conn)
                break;
        }
 
-       rc = isert_rx_opcode(isert_conn, rx_desc,
-                            read_stag, read_va, write_stag, write_va);
+       isert_rx_opcode(isert_conn, rx_desc,
+                       read_stag, read_va, write_stag, write_va);
 }
 
 static void
@@ -1589,7 +1581,7 @@ isert_rcv_completion(struct iser_rx_desc *desc,
        struct ib_device *ib_dev = isert_conn->cm_id->device;
        struct iscsi_hdr *hdr;
        u64 rx_dma;
-       int rx_buflen, outstanding;
+       int rx_buflen;
 
        if ((char *)desc == isert_conn->login_req_buf) {
                rx_dma = isert_conn->login_req_dma;
@@ -1629,22 +1621,6 @@ isert_rcv_completion(struct iser_rx_desc *desc,
                                      DMA_FROM_DEVICE);
 
        isert_conn->post_recv_buf_count--;
-       isert_dbg("Decremented post_recv_buf_count: %d\n",
-                 isert_conn->post_recv_buf_count);
-
-       if ((char *)desc == isert_conn->login_req_buf)
-               return;
-
-       outstanding = isert_conn->post_recv_buf_count;
-       if (outstanding + ISERT_MIN_POSTED_RX <= ISERT_QP_MAX_RECV_DTOS) {
-               int err, count = min(ISERT_QP_MAX_RECV_DTOS - outstanding,
-                               ISERT_MIN_POSTED_RX);
-               err = isert_post_recv(isert_conn, count);
-               if (err) {
-                       isert_err("isert_post_recv() count: %d failed, %d\n",
-                              count, err);
-               }
-       }
 }
 
 static int
@@ -1703,10 +1679,10 @@ isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn)
                isert_unmap_data_buf(isert_conn, &wr->data);
        }
 
-       if (wr->send_wr) {
+       if (wr->rdma_wr) {
                isert_dbg("Cmd %p free send_wr\n", isert_cmd);
-               kfree(wr->send_wr);
-               wr->send_wr = NULL;
+               kfree(wr->rdma_wr);
+               wr->rdma_wr = NULL;
        }
 
        if (wr->ib_sge) {
@@ -1741,7 +1717,7 @@ isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn)
        }
 
        wr->ib_sge = NULL;
-       wr->send_wr = NULL;
+       wr->rdma_wr = NULL;
 }
 
 static void
@@ -1774,7 +1750,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
                            cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) {
                                struct se_cmd *se_cmd = &cmd->se_cmd;
 
-                               target_put_sess_cmd(se_cmd->se_sess, se_cmd);
+                               target_put_sess_cmd(se_cmd);
                        }
                }
 
@@ -1910,7 +1886,7 @@ isert_completion_rdma_write(struct iser_tx_desc *tx_desc,
        }
 
        device->unreg_rdma_mem(isert_cmd, isert_conn);
-       wr->send_wr_num = 0;
+       wr->rdma_wr_num = 0;
        if (ret)
                transport_send_check_condition_and_sense(se_cmd,
                                                         se_cmd->pi_err, 0);
@@ -1938,7 +1914,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
        iscsit_stop_dataout_timer(cmd);
        device->unreg_rdma_mem(isert_cmd, isert_conn);
        cmd->write_data_done = wr->data.len;
-       wr->send_wr_num = 0;
+       wr->rdma_wr_num = 0;
 
        isert_dbg("Cmd: %p RDMA_READ comp calling execute_cmd\n", isert_cmd);
        spin_lock_bh(&cmd->istate_lock);
@@ -1947,7 +1923,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
        spin_unlock_bh(&cmd->istate_lock);
 
        if (ret) {
-               target_put_sess_cmd(se_cmd->se_sess, se_cmd);
+               target_put_sess_cmd(se_cmd);
                transport_send_check_condition_and_sense(se_cmd,
                                                         se_cmd->pi_err, 0);
        } else {
@@ -2108,10 +2084,13 @@ isert_handle_wc(struct ib_wc *wc)
                }
        } else {
                if (wc->status != IB_WC_WR_FLUSH_ERR)
-                       isert_err("wr id %llx status %d vend_err %x\n",
-                                 wc->wr_id, wc->status, wc->vendor_err);
+                       isert_err("%s (%d): wr id %llx vend_err %x\n",
+                                 ib_wc_status_msg(wc->status), wc->status,
+                                 wc->wr_id, wc->vendor_err);
                else
-                       isert_dbg("flush error: wr id %llx\n", wc->wr_id);
+                       isert_dbg("%s (%d): wr id %llx\n",
+                                 ib_wc_status_msg(wc->status), wc->status,
+                                 wc->wr_id);
 
                if (wc->wr_id != ISER_FASTREG_LI_WRID)
                        isert_cq_comp_err(isert_conn, wc);
@@ -2153,6 +2132,12 @@ isert_post_response(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd)
        struct ib_send_wr *wr_failed;
        int ret;
 
+       ret = isert_post_recv(isert_conn, isert_cmd->rx_desc);
+       if (ret) {
+               isert_err("ib_post_recv failed with %d\n", ret);
+               return ret;
+       }
+
        ret = ib_post_send(isert_conn->qp, &isert_cmd->tx_desc.send_wr,
                           &wr_failed);
        if (ret) {
@@ -2200,7 +2185,7 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                isert_cmd->pdu_buf_len = pdu_len;
                tx_dsg->addr    = isert_cmd->pdu_buf_dma;
                tx_dsg->length  = pdu_len;
-               tx_dsg->lkey    = device->mr->lkey;
+               tx_dsg->lkey    = device->pd->local_dma_lkey;
                isert_cmd->tx_desc.num_sge = 2;
        }
 
@@ -2328,7 +2313,7 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        isert_cmd->pdu_buf_len = ISCSI_HDR_LEN;
        tx_dsg->addr    = isert_cmd->pdu_buf_dma;
        tx_dsg->length  = ISCSI_HDR_LEN;
-       tx_dsg->lkey    = device->mr->lkey;
+       tx_dsg->lkey    = device->pd->local_dma_lkey;
        isert_cmd->tx_desc.num_sge = 2;
 
        isert_init_send_wr(isert_conn, isert_cmd, send_wr);
@@ -2369,7 +2354,7 @@ isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
                isert_cmd->pdu_buf_len = txt_rsp_len;
                tx_dsg->addr    = isert_cmd->pdu_buf_dma;
                tx_dsg->length  = txt_rsp_len;
-               tx_dsg->lkey    = device->mr->lkey;
+               tx_dsg->lkey    = device->pd->local_dma_lkey;
                isert_cmd->tx_desc.num_sge = 2;
        }
        isert_init_send_wr(isert_conn, isert_cmd, send_wr);
@@ -2381,7 +2366,7 @@ isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 
 static int
 isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
-                   struct ib_sge *ib_sge, struct ib_send_wr *send_wr,
+                   struct ib_sge *ib_sge, struct ib_rdma_wr *rdma_wr,
                    u32 data_left, u32 offset)
 {
        struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
@@ -2396,8 +2381,8 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
        sg_nents = min(cmd->se_cmd.t_data_nents - sg_off, isert_conn->max_sge);
        page_off = offset % PAGE_SIZE;
 
-       send_wr->sg_list = ib_sge;
-       send_wr->wr_id = (uintptr_t)&isert_cmd->tx_desc;
+       rdma_wr->wr.sg_list = ib_sge;
+       rdma_wr->wr.wr_id = (uintptr_t)&isert_cmd->tx_desc;
        /*
         * Perform mapping of TCM scatterlist memory ib_sge dma_addr.
         */
@@ -2410,7 +2395,7 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
                ib_sge->addr = ib_sg_dma_address(ib_dev, tmp_sg) + page_off;
                ib_sge->length = min_t(u32, data_left,
                                ib_sg_dma_len(ib_dev, tmp_sg) - page_off);
-               ib_sge->lkey = device->mr->lkey;
+               ib_sge->lkey = device->pd->local_dma_lkey;
 
                isert_dbg("RDMA ib_sge: addr: 0x%llx  length: %u lkey: %x\n",
                          ib_sge->addr, ib_sge->length, ib_sge->lkey);
@@ -2422,11 +2407,11 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
                isert_dbg("Incrementing ib_sge pointer to %p\n", ib_sge);
        }
 
-       send_wr->num_sge = ++i;
+       rdma_wr->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);
+                 rdma_wr->wr.sg_list, rdma_wr->wr.num_sge);
 
-       return send_wr->num_sge;
+       return rdma_wr->wr.num_sge;
 }
 
 static int
@@ -2437,7 +2422,7 @@ isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
        struct isert_conn *isert_conn = conn->context;
        struct isert_data_buf *data = &wr->data;
-       struct ib_send_wr *send_wr;
+       struct ib_rdma_wr *rdma_wr;
        struct ib_sge *ib_sge;
        u32 offset, data_len, data_left, rdma_write_max, va_offset = 0;
        int ret = 0, i, ib_sge_cnt;
@@ -2462,11 +2447,11 @@ isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        }
        wr->ib_sge = ib_sge;
 
-       wr->send_wr_num = DIV_ROUND_UP(data->nents, isert_conn->max_sge);
-       wr->send_wr = kzalloc(sizeof(struct ib_send_wr) * wr->send_wr_num,
+       wr->rdma_wr_num = DIV_ROUND_UP(data->nents, isert_conn->max_sge);
+       wr->rdma_wr = kzalloc(sizeof(struct ib_rdma_wr) * wr->rdma_wr_num,
                                GFP_KERNEL);
-       if (!wr->send_wr) {
-               isert_dbg("Unable to allocate wr->send_wr\n");
+       if (!wr->rdma_wr) {
+               isert_dbg("Unable to allocate wr->rdma_wr\n");
                ret = -ENOMEM;
                goto unmap_cmd;
        }
@@ -2474,31 +2459,31 @@ isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        wr->isert_cmd = isert_cmd;
        rdma_write_max = isert_conn->max_sge * PAGE_SIZE;
 
-       for (i = 0; i < wr->send_wr_num; i++) {
-               send_wr = &isert_cmd->rdma_wr.send_wr[i];
+       for (i = 0; i < wr->rdma_wr_num; i++) {
+               rdma_wr = &isert_cmd->rdma_wr.rdma_wr[i];
                data_len = min(data_left, rdma_write_max);
 
-               send_wr->send_flags = 0;
+               rdma_wr->wr.send_flags = 0;
                if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) {
-                       send_wr->opcode = IB_WR_RDMA_WRITE;
-                       send_wr->wr.rdma.remote_addr = isert_cmd->read_va + offset;
-                       send_wr->wr.rdma.rkey = isert_cmd->read_stag;
-                       if (i + 1 == wr->send_wr_num)
-                               send_wr->next = &isert_cmd->tx_desc.send_wr;
+                       rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+                       rdma_wr->remote_addr = isert_cmd->read_va + offset;
+                       rdma_wr->rkey = isert_cmd->read_stag;
+                       if (i + 1 == wr->rdma_wr_num)
+                               rdma_wr->wr.next = &isert_cmd->tx_desc.send_wr;
                        else
-                               send_wr->next = &wr->send_wr[i + 1];
+                               rdma_wr->wr.next = &wr->rdma_wr[i + 1].wr;
                } else {
-                       send_wr->opcode = IB_WR_RDMA_READ;
-                       send_wr->wr.rdma.remote_addr = isert_cmd->write_va + va_offset;
-                       send_wr->wr.rdma.rkey = isert_cmd->write_stag;
-                       if (i + 1 == wr->send_wr_num)
-                               send_wr->send_flags = IB_SEND_SIGNALED;
+                       rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+                       rdma_wr->remote_addr = isert_cmd->write_va + va_offset;
+                       rdma_wr->rkey = isert_cmd->write_stag;
+                       if (i + 1 == wr->rdma_wr_num)
+                               rdma_wr->wr.send_flags = IB_SEND_SIGNALED;
                        else
-                               send_wr->next = &wr->send_wr[i + 1];
+                               rdma_wr->wr.next = &wr->rdma_wr[i + 1].wr;
                }
 
                ib_sge_cnt = isert_build_rdma_wr(isert_conn, isert_cmd, ib_sge,
-                                       send_wr, data_len, offset);
+                                       rdma_wr, data_len, offset);
                ib_sge += ib_sge_cnt;
 
                offset += data_len;
@@ -2513,45 +2498,6 @@ unmap_cmd:
        return ret;
 }
 
-static int
-isert_map_fr_pagelist(struct ib_device *ib_dev,
-                     struct scatterlist *sg_start, int sg_nents, u64 *fr_pl)
-{
-       u64 start_addr, end_addr, page, chunk_start = 0;
-       struct scatterlist *tmp_sg;
-       int i = 0, new_chunk, last_ent, n_pages;
-
-       n_pages = 0;
-       new_chunk = 1;
-       last_ent = sg_nents - 1;
-       for_each_sg(sg_start, tmp_sg, sg_nents, i) {
-               start_addr = ib_sg_dma_address(ib_dev, tmp_sg);
-               if (new_chunk)
-                       chunk_start = start_addr;
-               end_addr = start_addr + ib_sg_dma_len(ib_dev, tmp_sg);
-
-               isert_dbg("SGL[%d] dma_addr: 0x%llx len: %u\n",
-                         i, (unsigned long long)tmp_sg->dma_address,
-                         tmp_sg->length);
-
-               if ((end_addr & ~PAGE_MASK) && i < last_ent) {
-                       new_chunk = 0;
-                       continue;
-               }
-               new_chunk = 1;
-
-               page = chunk_start & PAGE_MASK;
-               do {
-                       fr_pl[n_pages++] = page;
-                       isert_dbg("Mapped page_list[%d] page_addr: 0x%llx\n",
-                                 n_pages - 1, page);
-                       page += PAGE_SIZE;
-               } while (page < end_addr);
-       }
-
-       return n_pages;
-}
-
 static inline void
 isert_inv_rkey(struct ib_send_wr *inv_wr, struct ib_mr *mr)
 {
@@ -2577,14 +2523,12 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
        struct isert_device *device = isert_conn->device;
        struct ib_device *ib_dev = device->ib_device;
        struct ib_mr *mr;
-       struct ib_fast_reg_page_list *frpl;
-       struct ib_send_wr fr_wr, inv_wr;
-       struct ib_send_wr *bad_wr, *wr = NULL;
-       int ret, pagelist_len;
-       u32 page_off;
+       struct ib_reg_wr reg_wr;
+       struct ib_send_wr inv_wr, *bad_wr, *wr = NULL;
+       int ret, n;
 
        if (mem->dma_nents == 1) {
-               sge->lkey = device->mr->lkey;
+               sge->lkey = device->pd->local_dma_lkey;
                sge->addr = ib_sg_dma_address(ib_dev, &mem->sg[0]);
                sge->length = ib_sg_dma_len(ib_dev, &mem->sg[0]);
                isert_dbg("sge: addr: 0x%llx  length: %u lkey: %x\n",
@@ -2592,45 +2536,41 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
                return 0;
        }
 
-       if (ind == ISERT_DATA_KEY_VALID) {
+       if (ind == ISERT_DATA_KEY_VALID)
                /* Registering data buffer */
                mr = fr_desc->data_mr;
-               frpl = fr_desc->data_frpl;
-       } else {
+       else
                /* Registering protection buffer */
                mr = fr_desc->pi_ctx->prot_mr;
-               frpl = fr_desc->pi_ctx->prot_frpl;
-       }
-
-       page_off = mem->offset % PAGE_SIZE;
-
-       isert_dbg("Use fr_desc %p sg_nents %d offset %u\n",
-                 fr_desc, mem->nents, mem->offset);
-
-       pagelist_len = isert_map_fr_pagelist(ib_dev, mem->sg, mem->nents,
-                                            &frpl->page_list[0]);
 
        if (!(fr_desc->ind & ind)) {
                isert_inv_rkey(&inv_wr, mr);
                wr = &inv_wr;
        }
 
-       /* Prepare FASTREG WR */
-       memset(&fr_wr, 0, sizeof(fr_wr));
-       fr_wr.wr_id = ISER_FASTREG_LI_WRID;
-       fr_wr.opcode = IB_WR_FAST_REG_MR;
-       fr_wr.wr.fast_reg.iova_start = frpl->page_list[0] + page_off;
-       fr_wr.wr.fast_reg.page_list = frpl;
-       fr_wr.wr.fast_reg.page_list_len = pagelist_len;
-       fr_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
-       fr_wr.wr.fast_reg.length = mem->len;
-       fr_wr.wr.fast_reg.rkey = mr->rkey;
-       fr_wr.wr.fast_reg.access_flags = IB_ACCESS_LOCAL_WRITE;
+       n = ib_map_mr_sg(mr, mem->sg, mem->nents, PAGE_SIZE);
+       if (unlikely(n != mem->nents)) {
+               isert_err("failed to map mr sg (%d/%d)\n",
+                        n, mem->nents);
+               return n < 0 ? n : -EINVAL;
+       }
+
+       isert_dbg("Use fr_desc %p sg_nents %d offset %u\n",
+                 fr_desc, mem->nents, mem->offset);
+
+       reg_wr.wr.next = NULL;
+       reg_wr.wr.opcode = IB_WR_REG_MR;
+       reg_wr.wr.wr_id = ISER_FASTREG_LI_WRID;
+       reg_wr.wr.send_flags = 0;
+       reg_wr.wr.num_sge = 0;
+       reg_wr.mr = mr;
+       reg_wr.key = mr->lkey;
+       reg_wr.access = IB_ACCESS_LOCAL_WRITE;
 
        if (!wr)
-               wr = &fr_wr;
+               wr = &reg_wr.wr;
        else
-               wr->next = &fr_wr;
+               wr->next = &reg_wr.wr;
 
        ret = ib_post_send(isert_conn->qp, wr, &bad_wr);
        if (ret) {
@@ -2640,8 +2580,8 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
        fr_desc->ind &= ~ind;
 
        sge->lkey = mr->lkey;
-       sge->addr = frpl->page_list[0] + page_off;
-       sge->length = mem->len;
+       sge->addr = mr->iova;
+       sge->length = mr->length;
 
        isert_dbg("sge: addr: 0x%llx  length: %u lkey: %x\n",
                  sge->addr, sge->length, sge->lkey);
@@ -2711,8 +2651,8 @@ isert_reg_sig_mr(struct isert_conn *isert_conn,
                 struct isert_rdma_wr *rdma_wr,
                 struct fast_reg_descriptor *fr_desc)
 {
-       struct ib_send_wr sig_wr, inv_wr;
-       struct ib_send_wr *bad_wr, *wr = NULL;
+       struct ib_sig_handover_wr sig_wr;
+       struct ib_send_wr inv_wr, *bad_wr, *wr = NULL;
        struct pi_context *pi_ctx = fr_desc->pi_ctx;
        struct ib_sig_attrs sig_attrs;
        int ret;
@@ -2730,20 +2670,20 @@ isert_reg_sig_mr(struct isert_conn *isert_conn,
        }
 
        memset(&sig_wr, 0, sizeof(sig_wr));
-       sig_wr.opcode = IB_WR_REG_SIG_MR;
-       sig_wr.wr_id = ISER_FASTREG_LI_WRID;
-       sig_wr.sg_list = &rdma_wr->ib_sg[DATA];
-       sig_wr.num_sge = 1;
-       sig_wr.wr.sig_handover.access_flags = IB_ACCESS_LOCAL_WRITE;
-       sig_wr.wr.sig_handover.sig_attrs = &sig_attrs;
-       sig_wr.wr.sig_handover.sig_mr = pi_ctx->sig_mr;
+       sig_wr.wr.opcode = IB_WR_REG_SIG_MR;
+       sig_wr.wr.wr_id = ISER_FASTREG_LI_WRID;
+       sig_wr.wr.sg_list = &rdma_wr->ib_sg[DATA];
+       sig_wr.wr.num_sge = 1;
+       sig_wr.access_flags = IB_ACCESS_LOCAL_WRITE;
+       sig_wr.sig_attrs = &sig_attrs;
+       sig_wr.sig_mr = pi_ctx->sig_mr;
        if (se_cmd->t_prot_sg)
-               sig_wr.wr.sig_handover.prot = &rdma_wr->ib_sg[PROT];
+               sig_wr.prot = &rdma_wr->ib_sg[PROT];
 
        if (!wr)
-               wr = &sig_wr;
+               wr = &sig_wr.wr;
        else
-               wr->next = &sig_wr;
+               wr->next = &sig_wr.wr;
 
        ret = ib_post_send(isert_conn->qp, wr, &bad_wr);
        if (ret) {
@@ -2837,7 +2777,7 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
        struct isert_conn *isert_conn = conn->context;
        struct fast_reg_descriptor *fr_desc = NULL;
-       struct ib_send_wr *send_wr;
+       struct ib_rdma_wr *rdma_wr;
        struct ib_sge *ib_sg;
        u32 offset;
        int ret = 0;
@@ -2878,26 +2818,26 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 
        memcpy(&wr->s_ib_sge, ib_sg, sizeof(*ib_sg));
        wr->ib_sge = &wr->s_ib_sge;
-       wr->send_wr_num = 1;
-       memset(&wr->s_send_wr, 0, sizeof(*send_wr));
-       wr->send_wr = &wr->s_send_wr;
+       wr->rdma_wr_num = 1;
+       memset(&wr->s_rdma_wr, 0, sizeof(wr->s_rdma_wr));
+       wr->rdma_wr = &wr->s_rdma_wr;
        wr->isert_cmd = isert_cmd;
 
-       send_wr = &isert_cmd->rdma_wr.s_send_wr;
-       send_wr->sg_list = &wr->s_ib_sge;
-       send_wr->num_sge = 1;
-       send_wr->wr_id = (uintptr_t)&isert_cmd->tx_desc;
+       rdma_wr = &isert_cmd->rdma_wr.s_rdma_wr;
+       rdma_wr->wr.sg_list = &wr->s_ib_sge;
+       rdma_wr->wr.num_sge = 1;
+       rdma_wr->wr.wr_id = (uintptr_t)&isert_cmd->tx_desc;
        if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) {
-               send_wr->opcode = IB_WR_RDMA_WRITE;
-               send_wr->wr.rdma.remote_addr = isert_cmd->read_va;
-               send_wr->wr.rdma.rkey = isert_cmd->read_stag;
-               send_wr->send_flags = !isert_prot_cmd(isert_conn, se_cmd) ?
+               rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+               rdma_wr->remote_addr = isert_cmd->read_va;
+               rdma_wr->rkey = isert_cmd->read_stag;
+               rdma_wr->wr.send_flags = !isert_prot_cmd(isert_conn, se_cmd) ?
                                      0 : IB_SEND_SIGNALED;
        } else {
-               send_wr->opcode = IB_WR_RDMA_READ;
-               send_wr->wr.rdma.remote_addr = isert_cmd->write_va;
-               send_wr->wr.rdma.rkey = isert_cmd->write_stag;
-               send_wr->send_flags = IB_SEND_SIGNALED;
+               rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+               rdma_wr->remote_addr = isert_cmd->write_va;
+               rdma_wr->rkey = isert_cmd->write_stag;
+               rdma_wr->wr.send_flags = IB_SEND_SIGNALED;
        }
 
        return 0;
@@ -2945,11 +2885,17 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
                isert_init_send_wr(isert_conn, isert_cmd,
                                   &isert_cmd->tx_desc.send_wr);
-               isert_cmd->rdma_wr.s_send_wr.next = &isert_cmd->tx_desc.send_wr;
-               wr->send_wr_num += 1;
+               isert_cmd->rdma_wr.s_rdma_wr.wr.next = &isert_cmd->tx_desc.send_wr;
+               wr->rdma_wr_num += 1;
+
+               rc = isert_post_recv(isert_conn, isert_cmd->rx_desc);
+               if (rc) {
+                       isert_err("ib_post_recv failed with %d\n", rc);
+                       return rc;
+               }
        }
 
-       rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
+       rc = ib_post_send(isert_conn->qp, &wr->rdma_wr->wr, &wr_failed);
        if (rc)
                isert_warn("ib_post_send() failed for IB_WR_RDMA_WRITE\n");
 
@@ -2983,7 +2929,7 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
                return rc;
        }
 
-       rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
+       rc = ib_post_send(isert_conn->qp, &wr->rdma_wr->wr, &wr_failed);
        if (rc)
                isert_warn("ib_post_send() failed for IB_WR_RDMA_READ\n");
 
@@ -2996,9 +2942,16 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
 static int
 isert_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
 {
-       int ret;
+       struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
+       int ret = 0;
 
        switch (state) {
+       case ISTATE_REMOVE:
+               spin_lock_bh(&conn->cmd_lock);
+               list_del_init(&cmd->i_conn_node);
+               spin_unlock_bh(&conn->cmd_lock);
+               isert_put_cmd(isert_cmd, true);
+               break;
        case ISTATE_SEND_NOPIN_WANT_RESPONSE:
                ret = isert_put_nopin(cmd, conn, false);
                break;
@@ -3062,7 +3015,7 @@ isert_setup_id(struct isert_np *isert_np)
        sa = (struct sockaddr *)&np->np_sockaddr;
        isert_dbg("ksockaddr: %p, sa: %p\n", &np->np_sockaddr, sa);
 
-       id = rdma_create_id(isert_cma_handler, isert_np,
+       id = rdma_create_id(&init_net, isert_cma_handler, isert_np,
                            RDMA_PS_TCP, IB_QPT_RC);
        if (IS_ERR(id)) {
                isert_err("rdma_create_id() failed: %ld\n", PTR_ERR(id));
@@ -3092,7 +3045,7 @@ out:
 
 static int
 isert_setup_np(struct iscsi_np *np,
-              struct __kernel_sockaddr_storage *ksockaddr)
+              struct sockaddr_storage *ksockaddr)
 {
        struct isert_np *isert_np;
        struct rdma_cm_id *isert_lid;
@@ -3103,10 +3056,10 @@ isert_setup_np(struct iscsi_np *np,
                isert_err("Unable to allocate struct isert_np\n");
                return -ENOMEM;
        }
-       sema_init(&isert_np->np_sem, 0);
-       mutex_init(&isert_np->np_accept_mutex);
-       INIT_LIST_HEAD(&isert_np->np_accept_list);
-       init_completion(&isert_np->np_login_comp);
+       sema_init(&isert_np->sem, 0);
+       mutex_init(&isert_np->mutex);
+       INIT_LIST_HEAD(&isert_np->accepted);
+       INIT_LIST_HEAD(&isert_np->pending);
        isert_np->np = np;
 
        /*
@@ -3114,7 +3067,7 @@ isert_setup_np(struct iscsi_np *np,
         * in iscsi_target_configfs.c code..
         */
        memcpy(&np->np_sockaddr, ksockaddr,
-              sizeof(struct __kernel_sockaddr_storage));
+              sizeof(struct sockaddr_storage));
 
        isert_lid = isert_setup_id(isert_np);
        if (IS_ERR(isert_lid)) {
@@ -3122,7 +3075,7 @@ isert_setup_np(struct iscsi_np *np,
                goto out;
        }
 
-       isert_np->np_cm_id = isert_lid;
+       isert_np->cm_id = isert_lid;
        np->np_context = isert_np;
 
        return 0;
@@ -3196,32 +3149,11 @@ isert_set_conn_info(struct iscsi_np *np, struct iscsi_conn *conn,
 {
        struct rdma_cm_id *cm_id = isert_conn->cm_id;
        struct rdma_route *cm_route = &cm_id->route;
-       struct sockaddr_in *sock_in;
-       struct sockaddr_in6 *sock_in6;
 
        conn->login_family = np->np_sockaddr.ss_family;
 
-       if (np->np_sockaddr.ss_family == AF_INET6) {
-               sock_in6 = (struct sockaddr_in6 *)&cm_route->addr.dst_addr;
-               snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
-                        &sock_in6->sin6_addr.in6_u);
-               conn->login_port = ntohs(sock_in6->sin6_port);
-
-               sock_in6 = (struct sockaddr_in6 *)&cm_route->addr.src_addr;
-               snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
-                        &sock_in6->sin6_addr.in6_u);
-               conn->local_port = ntohs(sock_in6->sin6_port);
-       } else {
-               sock_in = (struct sockaddr_in *)&cm_route->addr.dst_addr;
-               sprintf(conn->login_ip, "%pI4",
-                       &sock_in->sin_addr.s_addr);
-               conn->login_port = ntohs(sock_in->sin_port);
-
-               sock_in = (struct sockaddr_in *)&cm_route->addr.src_addr;
-               sprintf(conn->local_ip, "%pI4",
-                       &sock_in->sin_addr.s_addr);
-               conn->local_port = ntohs(sock_in->sin_port);
-       }
+       conn->login_sockaddr = cm_route->addr.dst_addr;
+       conn->local_sockaddr = cm_route->addr.src_addr;
 }
 
 static int
@@ -3232,7 +3164,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
        int ret;
 
 accept_wait:
-       ret = down_interruptible(&isert_np->np_sem);
+       ret = down_interruptible(&isert_np->sem);
        if (ret)
                return -ENODEV;
 
@@ -3249,15 +3181,15 @@ accept_wait:
        }
        spin_unlock_bh(&np->np_thread_lock);
 
-       mutex_lock(&isert_np->np_accept_mutex);
-       if (list_empty(&isert_np->np_accept_list)) {
-               mutex_unlock(&isert_np->np_accept_mutex);
+       mutex_lock(&isert_np->mutex);
+       if (list_empty(&isert_np->pending)) {
+               mutex_unlock(&isert_np->mutex);
                goto accept_wait;
        }
-       isert_conn = list_first_entry(&isert_np->np_accept_list,
-                       struct isert_conn, accept_node);
-       list_del_init(&isert_conn->accept_node);
-       mutex_unlock(&isert_np->np_accept_mutex);
+       isert_conn = list_first_entry(&isert_np->pending,
+                       struct isert_conn, node);
+       list_del_init(&isert_conn->node);
+       mutex_unlock(&isert_np->mutex);
 
        conn->context = isert_conn;
        isert_conn->conn = conn;
@@ -3275,28 +3207,39 @@ isert_free_np(struct iscsi_np *np)
        struct isert_np *isert_np = np->np_context;
        struct isert_conn *isert_conn, *n;
 
-       if (isert_np->np_cm_id)
-               rdma_destroy_id(isert_np->np_cm_id);
+       if (isert_np->cm_id)
+               rdma_destroy_id(isert_np->cm_id);
 
        /*
         * FIXME: At this point we don't have a good way to insure
         * that at this point we don't have hanging connections that
         * completed RDMA establishment but didn't start iscsi login
         * process. So work-around this by cleaning up what ever piled
-        * up in np_accept_list.
+        * up in accepted and pending lists.
         */
-       mutex_lock(&isert_np->np_accept_mutex);
-       if (!list_empty(&isert_np->np_accept_list)) {
-               isert_info("Still have isert connections, cleaning up...\n");
+       mutex_lock(&isert_np->mutex);
+       if (!list_empty(&isert_np->pending)) {
+               isert_info("Still have isert pending connections\n");
                list_for_each_entry_safe(isert_conn, n,
-                                        &isert_np->np_accept_list,
-                                        accept_node) {
+                                        &isert_np->pending,
+                                        node) {
                        isert_info("cleaning isert_conn %p state (%d)\n",
                                   isert_conn, isert_conn->state);
                        isert_connect_release(isert_conn);
                }
        }
-       mutex_unlock(&isert_np->np_accept_mutex);
+
+       if (!list_empty(&isert_np->accepted)) {
+               isert_info("Still have isert accepted connections\n");
+               list_for_each_entry_safe(isert_conn, n,
+                                        &isert_np->accepted,
+                                        node) {
+                       isert_info("cleaning isert_conn %p state (%d)\n",
+                                  isert_conn, isert_conn->state);
+                       isert_connect_release(isert_conn);
+               }
+       }
+       mutex_unlock(&isert_np->mutex);
 
        np->np_context = NULL;
        kfree(isert_np);
@@ -3363,6 +3306,41 @@ isert_wait4flush(struct isert_conn *isert_conn)
        wait_for_completion(&isert_conn->wait_comp_err);
 }
 
+/**
+ * isert_put_unsol_pending_cmds() - Drop commands waiting for
+ *     unsolicitate dataout
+ * @conn:    iscsi connection
+ *
+ * We might still have commands that are waiting for unsolicited
+ * dataouts messages. We must put the extra reference on those
+ * before blocking on the target_wait_for_session_cmds
+ */
+static void
+isert_put_unsol_pending_cmds(struct iscsi_conn *conn)
+{
+       struct iscsi_cmd *cmd, *tmp;
+       static LIST_HEAD(drop_cmd_list);
+
+       spin_lock_bh(&conn->cmd_lock);
+       list_for_each_entry_safe(cmd, tmp, &conn->conn_cmd_list, i_conn_node) {
+               if ((cmd->cmd_flags & ICF_NON_IMMEDIATE_UNSOLICITED_DATA) &&
+                   (cmd->write_data_done < conn->sess->sess_ops->FirstBurstLength) &&
+                   (cmd->write_data_done < cmd->se_cmd.data_length))
+                       list_move_tail(&cmd->i_conn_node, &drop_cmd_list);
+       }
+       spin_unlock_bh(&conn->cmd_lock);
+
+       list_for_each_entry_safe(cmd, tmp, &drop_cmd_list, i_conn_node) {
+               list_del_init(&cmd->i_conn_node);
+               if (cmd->i_state != ISTATE_REMOVE) {
+                       struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
+
+                       isert_info("conn %p dropping cmd %p\n", conn, cmd);
+                       isert_put_cmd(isert_cmd, true);
+               }
+       }
+}
+
 static void isert_wait_conn(struct iscsi_conn *conn)
 {
        struct isert_conn *isert_conn = conn->context;
@@ -3381,8 +3359,9 @@ static void isert_wait_conn(struct iscsi_conn *conn)
        isert_conn_terminate(isert_conn);
        mutex_unlock(&isert_conn->mutex);
 
-       isert_wait4cmds(conn);
        isert_wait4flush(isert_conn);
+       isert_put_unsol_pending_cmds(conn);
+       isert_wait4cmds(conn);
        isert_wait4logout(isert_conn);
 
        queue_work(isert_release_wq, &isert_conn->release_work);