diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-06-14 19:47:15 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-07-07 21:36:48 -0400 |
commit | adb54c29310e8785e4f2eb0dc76e0e2fde943b11 (patch) | |
tree | a1741996414a81337ffccc8e56ff6dbca8b7c1d6 /drivers/infiniband/ulp/isert/ib_isert.c | |
parent | dbbc5d11074fc017488e6bdaaf9238d53e35ab07 (diff) |
iser-target: Add support for ISCSI_OP_TEXT opcode + payload handling
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.
It copies ISCSI_OP_TEXT payload using unsolicited payload at
&iser_rx_desc->data[0] into iscsi_cmd->text_in_ptr for usage
with outgoing isert_put_text_rsp() -> iscsit_build_text_rsp()
v2 changes:
- 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>
Diffstat (limited to 'drivers/infiniband/ulp/isert/ib_isert.c')
-rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.c | 89 |
1 files changed, 88 insertions, 1 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index fa4251803577..f02bfcc282e5 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c | |||
@@ -1033,6 +1033,33 @@ isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | |||
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | static int | 1035 | static int |
1036 | isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | ||
1037 | struct iser_rx_desc *rx_desc, struct iscsi_text *hdr) | ||
1038 | { | ||
1039 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; | ||
1040 | struct iscsi_conn *conn = isert_conn->conn; | ||
1041 | u32 payload_length = ntoh24(hdr->dlength); | ||
1042 | int rc; | ||
1043 | unsigned char *text_in; | ||
1044 | |||
1045 | rc = iscsit_setup_text_cmd(conn, cmd, hdr); | ||
1046 | if (rc < 0) | ||
1047 | return rc; | ||
1048 | |||
1049 | text_in = kzalloc(payload_length, GFP_KERNEL); | ||
1050 | if (!text_in) { | ||
1051 | pr_err("Unable to allocate text_in of payload_length: %u\n", | ||
1052 | payload_length); | ||
1053 | return -ENOMEM; | ||
1054 | } | ||
1055 | cmd->text_in_ptr = text_in; | ||
1056 | |||
1057 | memcpy(cmd->text_in_ptr, &rx_desc->data[0], payload_length); | ||
1058 | |||
1059 | return iscsit_process_text_cmd(conn, cmd, hdr); | ||
1060 | } | ||
1061 | |||
1062 | static int | ||
1036 | isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | 1063 | isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, |
1037 | uint32_t read_stag, uint64_t read_va, | 1064 | uint32_t read_stag, uint64_t read_va, |
1038 | uint32_t write_stag, uint64_t write_va) | 1065 | uint32_t write_stag, uint64_t write_va) |
@@ -1091,6 +1118,15 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | |||
1091 | SECONDS_FOR_LOGOUT_COMP * | 1118 | SECONDS_FOR_LOGOUT_COMP * |
1092 | HZ); | 1119 | HZ); |
1093 | break; | 1120 | break; |
1121 | case ISCSI_OP_TEXT: | ||
1122 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | ||
1123 | if (!cmd) | ||
1124 | break; | ||
1125 | |||
1126 | isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd); | ||
1127 | ret = isert_handle_text_cmd(isert_conn, isert_cmd, | ||
1128 | rx_desc, (struct iscsi_text *)hdr); | ||
1129 | break; | ||
1094 | default: | 1130 | default: |
1095 | pr_err("Got unknown iSCSI OpCode: 0x%02x\n", opcode); | 1131 | pr_err("Got unknown iSCSI OpCode: 0x%02x\n", opcode); |
1096 | dump_stack(); | 1132 | dump_stack(); |
@@ -1245,6 +1281,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd) | |||
1245 | break; | 1281 | break; |
1246 | case ISCSI_OP_REJECT: | 1282 | case ISCSI_OP_REJECT: |
1247 | case ISCSI_OP_NOOP_OUT: | 1283 | case ISCSI_OP_NOOP_OUT: |
1284 | case ISCSI_OP_TEXT: | ||
1248 | spin_lock_bh(&conn->cmd_lock); | 1285 | spin_lock_bh(&conn->cmd_lock); |
1249 | if (!list_empty(&cmd->i_conn_node)) | 1286 | if (!list_empty(&cmd->i_conn_node)) |
1250 | list_del(&cmd->i_conn_node); | 1287 | list_del(&cmd->i_conn_node); |
@@ -1366,6 +1403,11 @@ isert_do_control_comp(struct work_struct *work) | |||
1366 | isert_conn->logout_posted = true; | 1403 | isert_conn->logout_posted = true; |
1367 | iscsit_logout_post_handler(cmd, cmd->conn); | 1404 | iscsit_logout_post_handler(cmd, cmd->conn); |
1368 | break; | 1405 | break; |
1406 | case ISTATE_SEND_TEXTRSP: | ||
1407 | atomic_dec(&isert_conn->post_send_buf_count); | ||
1408 | cmd->i_state = ISTATE_SENT_STATUS; | ||
1409 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); | ||
1410 | break; | ||
1369 | default: | 1411 | default: |
1370 | pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state); | 1412 | pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state); |
1371 | dump_stack(); | 1413 | dump_stack(); |
@@ -1383,7 +1425,8 @@ isert_response_completion(struct iser_tx_desc *tx_desc, | |||
1383 | 1425 | ||
1384 | if (cmd->i_state == ISTATE_SEND_TASKMGTRSP || | 1426 | if (cmd->i_state == ISTATE_SEND_TASKMGTRSP || |
1385 | cmd->i_state == ISTATE_SEND_LOGOUTRSP || | 1427 | cmd->i_state == ISTATE_SEND_LOGOUTRSP || |
1386 | cmd->i_state == ISTATE_SEND_REJECT) { | 1428 | cmd->i_state == ISTATE_SEND_REJECT || |
1429 | cmd->i_state == ISTATE_SEND_TEXTRSP) { | ||
1387 | isert_unmap_tx_desc(tx_desc, ib_dev); | 1430 | isert_unmap_tx_desc(tx_desc, ib_dev); |
1388 | 1431 | ||
1389 | INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp); | 1432 | INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp); |
@@ -1709,6 +1752,47 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | |||
1709 | } | 1752 | } |
1710 | 1753 | ||
1711 | static int | 1754 | static int |
1755 | isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | ||
1756 | { | ||
1757 | struct isert_cmd *isert_cmd = container_of(cmd, | ||
1758 | struct isert_cmd, iscsi_cmd); | ||
1759 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | ||
1760 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | ||
1761 | struct iscsi_text_rsp *hdr = | ||
1762 | (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header; | ||
1763 | u32 txt_rsp_len; | ||
1764 | int rc; | ||
1765 | |||
1766 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | ||
1767 | rc = iscsit_build_text_rsp(cmd, conn, hdr); | ||
1768 | if (rc < 0) | ||
1769 | return rc; | ||
1770 | |||
1771 | txt_rsp_len = rc; | ||
1772 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | ||
1773 | |||
1774 | if (txt_rsp_len) { | ||
1775 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | ||
1776 | struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; | ||
1777 | void *txt_rsp_buf = cmd->buf_ptr; | ||
1778 | |||
1779 | isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, | ||
1780 | txt_rsp_buf, txt_rsp_len, DMA_TO_DEVICE); | ||
1781 | |||
1782 | isert_cmd->pdu_buf_len = txt_rsp_len; | ||
1783 | tx_dsg->addr = isert_cmd->pdu_buf_dma; | ||
1784 | tx_dsg->length = txt_rsp_len; | ||
1785 | tx_dsg->lkey = isert_conn->conn_mr->lkey; | ||
1786 | isert_cmd->tx_desc.num_sge = 2; | ||
1787 | } | ||
1788 | isert_init_send_wr(isert_cmd, send_wr); | ||
1789 | |||
1790 | pr_debug("Posting Text Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | ||
1791 | |||
1792 | return isert_post_response(isert_conn, isert_cmd); | ||
1793 | } | ||
1794 | |||
1795 | static int | ||
1712 | isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | 1796 | isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, |
1713 | struct ib_sge *ib_sge, struct ib_send_wr *send_wr, | 1797 | struct ib_sge *ib_sge, struct ib_send_wr *send_wr, |
1714 | u32 data_left, u32 offset) | 1798 | u32 data_left, u32 offset) |
@@ -2006,6 +2090,9 @@ isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) | |||
2006 | case ISTATE_SEND_REJECT: | 2090 | case ISTATE_SEND_REJECT: |
2007 | ret = isert_put_reject(cmd, conn); | 2091 | ret = isert_put_reject(cmd, conn); |
2008 | break; | 2092 | break; |
2093 | case ISTATE_SEND_TEXTRSP: | ||
2094 | ret = isert_put_text_rsp(cmd, conn); | ||
2095 | break; | ||
2009 | case ISTATE_SEND_STATUS: | 2096 | case ISTATE_SEND_STATUS: |
2010 | /* | 2097 | /* |
2011 | * Special case for sending non GOOD SCSI status from TX thread | 2098 | * Special case for sending non GOOD SCSI status from TX thread |