IB/iser: Suppress scsi command send completions
[cascardo/linux.git] / drivers / infiniband / ulp / iser / iser_initiator.c
index 8d44a40..5a489ea 100644 (file)
@@ -49,7 +49,7 @@ static int iser_prepare_read_cmd(struct iscsi_task *task)
 
 {
        struct iscsi_iser_task *iser_task = task->dd_data;
-       struct iser_device  *device = iser_task->ib_conn->device;
+       struct iser_device  *device = iser_task->iser_conn->ib_conn.device;
        struct iser_regd_buf *regd_buf;
        int err;
        struct iser_hdr *hdr = &iser_task->desc.iser_header;
@@ -103,7 +103,7 @@ iser_prepare_write_cmd(struct iscsi_task *task,
                       unsigned int edtl)
 {
        struct iscsi_iser_task *iser_task = task->dd_data;
-       struct iser_device  *device = iser_task->ib_conn->device;
+       struct iser_device  *device = iser_task->iser_conn->ib_conn.device;
        struct iser_regd_buf *regd_buf;
        int err;
        struct iser_hdr *hdr = &iser_task->desc.iser_header;
@@ -160,10 +160,10 @@ iser_prepare_write_cmd(struct iscsi_task *task,
 }
 
 /* creates a new tx descriptor and adds header regd buffer */
-static void iser_create_send_desc(struct iser_conn     *ib_conn,
+static void iser_create_send_desc(struct iser_conn     *iser_conn,
                                  struct iser_tx_desc   *tx_desc)
 {
-       struct iser_device *device = ib_conn->device;
+       struct iser_device *device = iser_conn->ib_conn.device;
 
        ib_dma_sync_single_for_cpu(device->ib_device,
                tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
@@ -179,103 +179,108 @@ static void iser_create_send_desc(struct iser_conn      *ib_conn,
        }
 }
 
-static void iser_free_login_buf(struct iser_conn *ib_conn)
+static void iser_free_login_buf(struct iser_conn *iser_conn)
 {
-       if (!ib_conn->login_buf)
+       struct iser_device *device = iser_conn->ib_conn.device;
+
+       if (!iser_conn->login_buf)
                return;
 
-       if (ib_conn->login_req_dma)
-               ib_dma_unmap_single(ib_conn->device->ib_device,
-                                   ib_conn->login_req_dma,
+       if (iser_conn->login_req_dma)
+               ib_dma_unmap_single(device->ib_device,
+                                   iser_conn->login_req_dma,
                                    ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
 
-       if (ib_conn->login_resp_dma)
-               ib_dma_unmap_single(ib_conn->device->ib_device,
-                                   ib_conn->login_resp_dma,
+       if (iser_conn->login_resp_dma)
+               ib_dma_unmap_single(device->ib_device,
+                                   iser_conn->login_resp_dma,
                                    ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
 
-       kfree(ib_conn->login_buf);
+       kfree(iser_conn->login_buf);
 
        /* make sure we never redo any unmapping */
-       ib_conn->login_req_dma = 0;
-       ib_conn->login_resp_dma = 0;
-       ib_conn->login_buf = NULL;
+       iser_conn->login_req_dma = 0;
+       iser_conn->login_resp_dma = 0;
+       iser_conn->login_buf = NULL;
 }
 
-static int iser_alloc_login_buf(struct iser_conn *ib_conn)
+static int iser_alloc_login_buf(struct iser_conn *iser_conn)
 {
-       struct iser_device      *device;
+       struct iser_device *device = iser_conn->ib_conn.device;
        int                     req_err, resp_err;
 
-       BUG_ON(ib_conn->device == NULL);
+       BUG_ON(device == NULL);
 
-       device = ib_conn->device;
-
-       ib_conn->login_buf = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
+       iser_conn->login_buf = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
                                     ISER_RX_LOGIN_SIZE, GFP_KERNEL);
-       if (!ib_conn->login_buf)
+       if (!iser_conn->login_buf)
                goto out_err;
 
-       ib_conn->login_req_buf  = ib_conn->login_buf;
-       ib_conn->login_resp_buf = ib_conn->login_buf +
+       iser_conn->login_req_buf  = iser_conn->login_buf;
+       iser_conn->login_resp_buf = iser_conn->login_buf +
                                                ISCSI_DEF_MAX_RECV_SEG_LEN;
 
-       ib_conn->login_req_dma = ib_dma_map_single(ib_conn->device->ib_device,
-                               (void *)ib_conn->login_req_buf,
-                               ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+       iser_conn->login_req_dma = ib_dma_map_single(device->ib_device,
+                                                    iser_conn->login_req_buf,
+                                                    ISCSI_DEF_MAX_RECV_SEG_LEN,
+                                                    DMA_TO_DEVICE);
 
-       ib_conn->login_resp_dma = ib_dma_map_single(ib_conn->device->ib_device,
-                               (void *)ib_conn->login_resp_buf,
-                               ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+       iser_conn->login_resp_dma = ib_dma_map_single(device->ib_device,
+                                                     iser_conn->login_resp_buf,
+                                                     ISER_RX_LOGIN_SIZE,
+                                                     DMA_FROM_DEVICE);
 
        req_err  = ib_dma_mapping_error(device->ib_device,
-                                       ib_conn->login_req_dma);
+                                       iser_conn->login_req_dma);
        resp_err = ib_dma_mapping_error(device->ib_device,
-                                       ib_conn->login_resp_dma);
+                                       iser_conn->login_resp_dma);
 
        if (req_err || resp_err) {
                if (req_err)
-                       ib_conn->login_req_dma = 0;
+                       iser_conn->login_req_dma = 0;
                if (resp_err)
-                       ib_conn->login_resp_dma = 0;
+                       iser_conn->login_resp_dma = 0;
                goto free_login_buf;
        }
        return 0;
 
 free_login_buf:
-       iser_free_login_buf(ib_conn);
+       iser_free_login_buf(iser_conn);
 
 out_err:
        iser_err("unable to alloc or map login buf\n");
        return -ENOMEM;
 }
 
-int iser_alloc_rx_descriptors(struct iser_conn *ib_conn, struct iscsi_session *session)
+int iser_alloc_rx_descriptors(struct iser_conn *iser_conn,
+                             struct iscsi_session *session)
 {
        int i, j;
        u64 dma_addr;
        struct iser_rx_desc *rx_desc;
        struct ib_sge       *rx_sg;
-       struct iser_device  *device = ib_conn->device;
+       struct ib_conn *ib_conn = &iser_conn->ib_conn;
+       struct iser_device *device = ib_conn->device;
 
-       ib_conn->qp_max_recv_dtos = session->cmds_max;
-       ib_conn->qp_max_recv_dtos_mask = session->cmds_max - 1; /* cmds_max is 2^N */
-       ib_conn->min_posted_rx = ib_conn->qp_max_recv_dtos >> 2;
+       iser_conn->qp_max_recv_dtos = session->cmds_max;
+       iser_conn->qp_max_recv_dtos_mask = session->cmds_max - 1; /* cmds_max is 2^N */
+       iser_conn->min_posted_rx = iser_conn->qp_max_recv_dtos >> 2;
 
        if (device->iser_alloc_rdma_reg_res(ib_conn, session->scsi_cmds_max))
                goto create_rdma_reg_res_failed;
 
-       if (iser_alloc_login_buf(ib_conn))
+       if (iser_alloc_login_buf(iser_conn))
                goto alloc_login_buf_fail;
 
-       ib_conn->rx_descs = kmalloc(session->cmds_max *
+       iser_conn->num_rx_descs = session->cmds_max;
+       iser_conn->rx_descs = kmalloc(iser_conn->num_rx_descs *
                                sizeof(struct iser_rx_desc), GFP_KERNEL);
-       if (!ib_conn->rx_descs)
+       if (!iser_conn->rx_descs)
                goto rx_desc_alloc_fail;
 
-       rx_desc = ib_conn->rx_descs;
+       rx_desc = iser_conn->rx_descs;
 
-       for (i = 0; i < ib_conn->qp_max_recv_dtos; i++, rx_desc++)  {
+       for (i = 0; i < iser_conn->qp_max_recv_dtos; i++, rx_desc++)  {
                dma_addr = ib_dma_map_single(device->ib_device, (void *)rx_desc,
                                        ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
                if (ib_dma_mapping_error(device->ib_device, dma_addr))
@@ -289,18 +294,18 @@ int iser_alloc_rx_descriptors(struct iser_conn *ib_conn, struct iscsi_session *s
                rx_sg->lkey   = device->mr->lkey;
        }
 
-       ib_conn->rx_desc_head = 0;
+       iser_conn->rx_desc_head = 0;
        return 0;
 
 rx_desc_dma_map_failed:
-       rx_desc = ib_conn->rx_descs;
+       rx_desc = iser_conn->rx_descs;
        for (j = 0; j < i; j++, rx_desc++)
                ib_dma_unmap_single(device->ib_device, rx_desc->dma_addr,
                                    ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
-       kfree(ib_conn->rx_descs);
-       ib_conn->rx_descs = NULL;
+       kfree(iser_conn->rx_descs);
+       iser_conn->rx_descs = NULL;
 rx_desc_alloc_fail:
-       iser_free_login_buf(ib_conn);
+       iser_free_login_buf(iser_conn);
 alloc_login_buf_fail:
        device->iser_free_rdma_reg_res(ib_conn);
 create_rdma_reg_res_failed:
@@ -308,33 +313,35 @@ create_rdma_reg_res_failed:
        return -ENOMEM;
 }
 
-void iser_free_rx_descriptors(struct iser_conn *ib_conn)
+void iser_free_rx_descriptors(struct iser_conn *iser_conn)
 {
        int i;
        struct iser_rx_desc *rx_desc;
+       struct ib_conn *ib_conn = &iser_conn->ib_conn;
        struct iser_device *device = ib_conn->device;
 
-       if (!ib_conn->rx_descs)
+       if (!iser_conn->rx_descs)
                goto free_login_buf;
 
        if (device->iser_free_rdma_reg_res)
                device->iser_free_rdma_reg_res(ib_conn);
 
-       rx_desc = ib_conn->rx_descs;
-       for (i = 0; i < ib_conn->qp_max_recv_dtos; i++, rx_desc++)
+       rx_desc = iser_conn->rx_descs;
+       for (i = 0; i < iser_conn->qp_max_recv_dtos; i++, rx_desc++)
                ib_dma_unmap_single(device->ib_device, rx_desc->dma_addr,
                                    ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
-       kfree(ib_conn->rx_descs);
+       kfree(iser_conn->rx_descs);
        /* make sure we never redo any unmapping */
-       ib_conn->rx_descs = NULL;
+       iser_conn->rx_descs = NULL;
 
 free_login_buf:
-       iser_free_login_buf(ib_conn);
+       iser_free_login_buf(iser_conn);
 }
 
 static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req)
 {
-       struct iser_conn *ib_conn = conn->dd_data;
+       struct iser_conn *iser_conn = conn->dd_data;
+       struct ib_conn *ib_conn = &iser_conn->ib_conn;
        struct iscsi_session *session = conn->session;
 
        iser_dbg("req op %x flags %x\n", req->opcode, req->flags);
@@ -343,34 +350,37 @@ static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req)
                return 0;
 
        /*
-        * Check that there is one posted recv buffer (for the last login
-        * response) and no posted send buffers left - they must have been
-        * consumed during previous login phases.
+        * Check that there is one posted recv buffer
+        * (for the last login response).
         */
        WARN_ON(ib_conn->post_recv_buf_count != 1);
-       WARN_ON(atomic_read(&ib_conn->post_send_buf_count) != 0);
 
        if (session->discovery_sess) {
                iser_info("Discovery session, re-using login RX buffer\n");
                return 0;
        } else
                iser_info("Normal session, posting batch of RX %d buffers\n",
-                         ib_conn->min_posted_rx);
+                         iser_conn->min_posted_rx);
 
        /* Initial post receive buffers */
-       if (iser_post_recvm(ib_conn, ib_conn->min_posted_rx))
+       if (iser_post_recvm(iser_conn, iser_conn->min_posted_rx))
                return -ENOMEM;
 
        return 0;
 }
 
+static inline bool iser_signal_comp(int sig_count)
+{
+       return ((sig_count % ISER_SIGNAL_CMD_COUNT) == 0);
+}
+
 /**
  * iser_send_command - send command PDU
  */
 int iser_send_command(struct iscsi_conn *conn,
                      struct iscsi_task *task)
 {
-       struct iser_conn *ib_conn = conn->dd_data;
+       struct iser_conn *iser_conn = conn->dd_data;
        struct iscsi_iser_task *iser_task = task->dd_data;
        unsigned long edtl;
        int err;
@@ -378,12 +388,13 @@ int iser_send_command(struct iscsi_conn *conn,
        struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)task->hdr;
        struct scsi_cmnd *sc  =  task->sc;
        struct iser_tx_desc *tx_desc = &iser_task->desc;
+       static unsigned sig_count;
 
        edtl = ntohl(hdr->data_length);
 
        /* build the tx desc regd header and add it to the tx desc dto */
        tx_desc->type = ISCSI_TX_SCSI_COMMAND;
-       iser_create_send_desc(ib_conn, tx_desc);
+       iser_create_send_desc(iser_conn, tx_desc);
 
        if (hdr->flags & ISCSI_FLAG_CMD_READ) {
                data_buf = &iser_task->data[ISER_DIR_IN];
@@ -423,7 +434,8 @@ int iser_send_command(struct iscsi_conn *conn,
 
        iser_task->status = ISER_TASK_STATUS_STARTED;
 
-       err = iser_post_send(ib_conn, tx_desc);
+       err = iser_post_send(&iser_conn->ib_conn, tx_desc,
+                            iser_signal_comp(++sig_count));
        if (!err)
                return 0;
 
@@ -439,7 +451,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
                       struct iscsi_task *task,
                       struct iscsi_data *hdr)
 {
-       struct iser_conn *ib_conn = conn->dd_data;
+       struct iser_conn *iser_conn = conn->dd_data;
        struct iscsi_iser_task *iser_task = task->dd_data;
        struct iser_tx_desc *tx_desc = NULL;
        struct iser_regd_buf *regd_buf;
@@ -488,7 +500,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
                 itt, buf_offset, data_seg_len);
 
 
-       err = iser_post_send(ib_conn, tx_desc);
+       err = iser_post_send(&iser_conn->ib_conn, tx_desc, true);
        if (!err)
                return 0;
 
@@ -501,7 +513,7 @@ send_data_out_error:
 int iser_send_control(struct iscsi_conn *conn,
                      struct iscsi_task *task)
 {
-       struct iser_conn *ib_conn = conn->dd_data;
+       struct iser_conn *iser_conn = conn->dd_data;
        struct iscsi_iser_task *iser_task = task->dd_data;
        struct iser_tx_desc *mdesc = &iser_task->desc;
        unsigned long data_seg_len;
@@ -510,9 +522,9 @@ int iser_send_control(struct iscsi_conn *conn,
 
        /* build the tx desc regd header and add it to the tx desc dto */
        mdesc->type = ISCSI_TX_CONTROL;
-       iser_create_send_desc(ib_conn, mdesc);
+       iser_create_send_desc(iser_conn, mdesc);
 
-       device = ib_conn->device;
+       device = iser_conn->ib_conn.device;
 
        data_seg_len = ntoh24(task->hdr->dlength);
 
@@ -524,16 +536,16 @@ int iser_send_control(struct iscsi_conn *conn,
                }
 
                ib_dma_sync_single_for_cpu(device->ib_device,
-                       ib_conn->login_req_dma, task->data_count,
+                       iser_conn->login_req_dma, task->data_count,
                        DMA_TO_DEVICE);
 
-               memcpy(ib_conn->login_req_buf, task->data, task->data_count);
+               memcpy(iser_conn->login_req_buf, task->data, task->data_count);
 
                ib_dma_sync_single_for_device(device->ib_device,
-                       ib_conn->login_req_dma, task->data_count,
+                       iser_conn->login_req_dma, task->data_count,
                        DMA_TO_DEVICE);
 
-               tx_dsg->addr    = ib_conn->login_req_dma;
+               tx_dsg->addr    = iser_conn->login_req_dma;
                tx_dsg->length  = task->data_count;
                tx_dsg->lkey    = device->mr->lkey;
                mdesc->num_sge = 2;
@@ -542,7 +554,7 @@ int iser_send_control(struct iscsi_conn *conn,
        if (task == conn->login_task) {
                iser_dbg("op %x dsl %lx, posting login rx buffer\n",
                         task->hdr->opcode, data_seg_len);
-               err = iser_post_recvl(ib_conn);
+               err = iser_post_recvl(iser_conn);
                if (err)
                        goto send_control_error;
                err = iser_post_rx_bufs(conn, task->hdr);
@@ -550,7 +562,7 @@ int iser_send_control(struct iscsi_conn *conn,
                        goto send_control_error;
        }
 
-       err = iser_post_send(ib_conn, mdesc);
+       err = iser_post_send(&iser_conn->ib_conn, mdesc, true);
        if (!err)
                return 0;
 
@@ -564,15 +576,17 @@ send_control_error:
  */
 void iser_rcv_completion(struct iser_rx_desc *rx_desc,
                         unsigned long rx_xfer_len,
-                        struct iser_conn *ib_conn)
+                        struct ib_conn *ib_conn)
 {
+       struct iser_conn *iser_conn = container_of(ib_conn, struct iser_conn,
+                                                  ib_conn);
        struct iscsi_hdr *hdr;
        u64 rx_dma;
        int rx_buflen, outstanding, count, err;
 
        /* differentiate between login to all other PDUs */
-       if ((char *)rx_desc == ib_conn->login_resp_buf) {
-               rx_dma = ib_conn->login_resp_dma;
+       if ((char *)rx_desc == iser_conn->login_resp_buf) {
+               rx_dma = iser_conn->login_resp_dma;
                rx_buflen = ISER_RX_LOGIN_SIZE;
        } else {
                rx_dma = rx_desc->dma_addr;
@@ -580,14 +594,14 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc,
        }
 
        ib_dma_sync_single_for_cpu(ib_conn->device->ib_device, rx_dma,
-                       rx_buflen, DMA_FROM_DEVICE);
+                                  rx_buflen, DMA_FROM_DEVICE);
 
        hdr = &rx_desc->iscsi_header;
 
        iser_dbg("op 0x%x itt 0x%x dlen %d\n", hdr->opcode,
                        hdr->itt, (int)(rx_xfer_len - ISER_HEADERS_LEN));
 
-       iscsi_iser_recv(ib_conn->iscsi_conn, hdr, rx_desc->data,
+       iscsi_iser_recv(iser_conn->iscsi_conn, hdr, rx_desc->data,
                        rx_xfer_len - ISER_HEADERS_LEN);
 
        ib_dma_sync_single_for_device(ib_conn->device->ib_device, rx_dma,
@@ -599,21 +613,21 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc,
         * for the posted rx bufs refcount to become zero handles everything   */
        ib_conn->post_recv_buf_count--;
 
-       if (rx_dma == ib_conn->login_resp_dma)
+       if (rx_dma == iser_conn->login_resp_dma)
                return;
 
        outstanding = ib_conn->post_recv_buf_count;
-       if (outstanding + ib_conn->min_posted_rx <= ib_conn->qp_max_recv_dtos) {
-               count = min(ib_conn->qp_max_recv_dtos - outstanding,
-                                               ib_conn->min_posted_rx);
-               err = iser_post_recvm(ib_conn, count);
+       if (outstanding + iser_conn->min_posted_rx <= iser_conn->qp_max_recv_dtos) {
+               count = min(iser_conn->qp_max_recv_dtos - outstanding,
+                           iser_conn->min_posted_rx);
+               err = iser_post_recvm(iser_conn, count);
                if (err)
                        iser_err("posting %d rx bufs err %d\n", count, err);
        }
 }
 
 void iser_snd_completion(struct iser_tx_desc *tx_desc,
-                       struct iser_conn *ib_conn)
+                       struct ib_conn *ib_conn)
 {
        struct iscsi_task *task;
        struct iser_device *device = ib_conn->device;
@@ -625,8 +639,6 @@ void iser_snd_completion(struct iser_tx_desc *tx_desc,
                tx_desc = NULL;
        }
 
-       atomic_dec(&ib_conn->post_send_buf_count);
-
        if (tx_desc && tx_desc->type == ISCSI_TX_CONTROL) {
                /* this arithmetic is legal by libiscsi dd_data allocation */
                task = (void *) ((long)(void *)tx_desc -
@@ -658,7 +670,7 @@ void iser_task_rdma_init(struct iscsi_iser_task *iser_task)
 
 void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
 {
-       struct iser_device *device = iser_task->ib_conn->device;
+       struct iser_device *device = iser_task->iser_conn->ib_conn.device;
        int is_rdma_data_aligned = 1;
        int is_rdma_prot_aligned = 1;
        int prot_count = scsi_prot_sg_count(iser_task->sc);