]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
iser-target: Initial support for ISCSI_OP_TEXT opcode
authorNicholas Bellinger <nab@linux-iscsi.org>
Fri, 14 Jun 2013 23:47:15 +0000 (16:47 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Wed, 26 Jun 2013 07:34:58 +0000 (00:34 -0700)
This patch adds isert_handle_text_cmd() to handle incoming
ISCSI_OP_TEXT PDU processing, along with isert_put_text_rsp()
for posting ISCSI_OP_TEXT_RSP ib_send_wr response.

Note this uses cmd->buf_ptr -> isert_cmd->sense_buf_[dma,len]
for the outgoing response payload.

v2: Let iscsit_build_text_rsp() determine any extra padding

Reported-by: Or Gerlitz <ogerlitz@mellanox.com>
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/infiniband/ulp/isert/ib_isert.c

index c48c9481025c98c8b7a9a6bc36c44289215d40c4..ca440f4ad8ea55e6db25e3dcd94ee73ec6c7e5a9 100644 (file)
@@ -1019,6 +1019,24 @@ isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
        return iscsit_process_nop_out(conn, cmd, hdr);
 }
 
+static int
+isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
+                     struct iser_rx_desc *rx_desc, struct iscsi_text *hdr)
+{
+       struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
+       struct iscsi_conn *conn = isert_conn->conn;
+       int rc;
+
+       rc = iscsit_setup_text_cmd(conn, cmd, hdr);
+       if (rc < 0)
+               return rc;
+
+       /*
+        * FIXME: Add support for TEXT payload parsing
+        */
+       return iscsit_process_text_cmd(conn, cmd, hdr);
+}
+
 static int
 isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                uint32_t read_stag, uint64_t read_va,
@@ -1078,6 +1096,15 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                                                    SECONDS_FOR_LOGOUT_COMP *
                                                    HZ);
                break;
+       case ISCSI_OP_TEXT:
+               cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+               if (!cmd)
+                       break;
+
+               isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd);
+               ret = isert_handle_text_cmd(isert_conn, isert_cmd,
+                                           rx_desc, (struct iscsi_text *)hdr);
+               break;
        default:
                pr_err("Got unknown iSCSI OpCode: 0x%02x\n", opcode);
                dump_stack();
@@ -1230,6 +1257,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
                break;
        case ISCSI_OP_REJECT:
        case ISCSI_OP_NOOP_OUT:
+       case ISTATE_SEND_TEXTRSP:
                conn = isert_conn->conn;
 
                spin_lock_bh(&conn->cmd_lock);
@@ -1350,6 +1378,11 @@ isert_do_control_comp(struct work_struct *work)
                isert_conn->logout_posted = true;
                iscsit_logout_post_handler(cmd, cmd->conn);
                break;
+       case ISTATE_SEND_TEXTRSP:
+               atomic_dec(&isert_conn->post_send_buf_count);
+               cmd->i_state = ISTATE_SENT_STATUS;
+               isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev);
+               break;
        default:
                pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state);
                dump_stack();
@@ -1366,7 +1399,8 @@ isert_response_completion(struct iser_tx_desc *tx_desc,
        struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
 
        if (cmd->i_state == ISTATE_SEND_TASKMGTRSP ||
-           cmd->i_state == ISTATE_SEND_LOGOUTRSP) {
+           cmd->i_state == ISTATE_SEND_LOGOUTRSP ||
+           cmd->i_state == ISTATE_SEND_TEXTRSP) {
                isert_unmap_tx_desc(tx_desc, ib_dev);
 
                INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp);
@@ -1670,6 +1704,47 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        return isert_post_response(isert_conn, isert_cmd);
 }
 
+static int
+isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+       struct isert_cmd *isert_cmd = container_of(cmd,
+                               struct isert_cmd, iscsi_cmd);
+       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
+       struct iscsi_text_rsp *hdr =
+               (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header;
+       u32 txt_rsp_len;
+       int rc;
+
+       isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc);
+       rc = iscsit_build_text_rsp(cmd, conn, hdr);
+       if (rc < 0)
+               return rc;
+
+       txt_rsp_len = rc;
+       isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
+
+       if (txt_rsp_len) {
+               struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+               struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1];
+               void *txt_rsp_buf = cmd->buf_ptr;
+
+               isert_cmd->sense_buf_dma = ib_dma_map_single(ib_dev,
+                               txt_rsp_buf, txt_rsp_len, DMA_TO_DEVICE);
+
+               isert_cmd->sense_buf_len = txt_rsp_len;
+               tx_dsg->addr    = isert_cmd->sense_buf_dma;
+               tx_dsg->length  = txt_rsp_len;
+               tx_dsg->lkey    = isert_conn->conn_mr->lkey;
+               isert_cmd->tx_desc.num_sge = 2;
+       }
+       isert_init_send_wr(isert_cmd, send_wr);
+
+       pr_debug("Posting Text Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n");
+
+       return isert_post_response(isert_conn, isert_cmd);
+}
+
 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,
@@ -1968,6 +2043,9 @@ isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
        case ISTATE_SEND_REJECT:
                ret = isert_put_reject(cmd, conn);
                break;
+       case ISTATE_SEND_TEXTRSP:
+               ret = isert_put_text_rsp(cmd, conn);
+               break;
        case ISTATE_SEND_STATUS:
                /*
                 * Special case for sending non GOOD SCSI status from TX thread