diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-11 15:57:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-11 15:57:19 -0400 |
commit | 6d2fa9e141ea56a571ec842fd4f3a86bea44a203 (patch) | |
tree | e419f95b7d080046f0f4d4d5041b42a0889f2f0a /drivers/infiniband/ulp/isert | |
parent | 0fb3767b0a5601dd0d528bc8dbefc0567a34b7ec (diff) | |
parent | ca40d24eb8fc3c194b4439493ecf6b2d703812b8 (diff) |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger:
"Lots of activity this round on performance improvements in target-core
while benchmarking the prototype scsi-mq initiator code with
vhost-scsi fabric ports, along with a number of iscsi/iser-target
improvements and hardening fixes for exception path cases post v3.10
merge.
The highlights include:
- Make persistent reservations APTPL buffer allocated on-demand, and
drop per t10_reservation buffer. (grover)
- Make virtual LUN=0 a NULLIO device, and skip allocation of NULLIO
device pages (grover)
- Add transport_cmd_check_stop write_pending bit to avoid extra
access of ->t_state_lock is WRITE I/O submission fast-path. (nab)
- Drop unnecessary CMD_T_DEV_ACTIVE check from
transport_lun_remove_cmd to avoid extra access of ->t_state_lock in
release fast-path. (nab)
- Avoid extra t_state_lock access in __target_execute_cmd fast-path
(nab)
- Drop unnecessary vhost-scsi wait_for_tasks=true usage +
->t_state_lock access in release fast-path. (nab)
- Convert vhost-scsi to use modern se_cmd->cmd_kref
TARGET_SCF_ACK_KREF usage (nab)
- Add tracepoints for SCSI commands being processed (roland)
- Refactoring of iscsi-target handling of ISCSI_OP_NOOP +
ISCSI_OP_TEXT to be transport independent (nab)
- Add iscsi-target SendTargets=$IQN support for in-band discovery
(nab)
- Add iser-target support for in-band discovery (nab + Or)
- Add iscsi-target demo-mode TPG authentication context support (nab)
- Fix isert_put_reject payload buffer post (nab)
- Fix iscsit_add_reject* usage for iser (nab)
- Fix iscsit_sequence_cmd reject handling for iser (nab)
- Fix ISCSI_OP_SCSI_TMFUNC handling for iser (nab)
- Fix session reset bug with RDMA_CM_EVENT_DISCONNECTED (nab)
The last five iscsi/iser-target items are CC'ed to stable, as they do
address issues present in v3.10 code. They are certainly larger than
I'd like for stable patch set, but are important to ensure proper
REJECT exception handling in iser-target for 3.10.y"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (51 commits)
iser-target: Ignore non TEXT + LOGOUT opcodes for discovery
target: make queue_tm_rsp() return void
target: remove unused codes from enum tcm_tmrsp_table
iscsi-target: kstrtou* configfs attribute parameter cleanups
iscsi-target: Fix tfc_tpg_auth_cit configfs length overflow
iscsi-target: Fix tfc_tpg_nacl_auth_cit configfs length overflow
iser-target: Add support for ISCSI_OP_TEXT opcode + payload handling
iser-target: Rename sense_buf_[dma,len] to pdu_[dma,len]
iser-target: Add vendor_err debug output
target: Add (obsolete) checking for PMI/LBA fields in READ CAPACITY(10)
target: Return correct sense data for IO past the end of a device
target: Add tracepoints for SCSI commands being processed
iser-target: Fix session reset bug with RDMA_CM_EVENT_DISCONNECTED
iscsi-target: Fix ISCSI_OP_SCSI_TMFUNC handling for iser
iscsi-target: Fix iscsit_sequence_cmd reject handling for iser
iscsi-target: Fix iscsit_add_reject* usage for iser
iser-target: Fix isert_put_reject payload buffer post
iscsi-target: missing kfree() on error path
iscsi-target: Drop left-over iscsi_conn->bad_hdr
target: Make core_scsi3_update_and_write_aptpl return sense_reason_t
...
Diffstat (limited to 'drivers/infiniband/ulp/isert')
-rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.c | 268 | ||||
-rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.h | 5 |
2 files changed, 228 insertions, 45 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 2693129055c1..3f62041222f2 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c | |||
@@ -388,6 +388,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | |||
388 | init_waitqueue_head(&isert_conn->conn_wait_comp_err); | 388 | init_waitqueue_head(&isert_conn->conn_wait_comp_err); |
389 | kref_init(&isert_conn->conn_kref); | 389 | kref_init(&isert_conn->conn_kref); |
390 | kref_get(&isert_conn->conn_kref); | 390 | kref_get(&isert_conn->conn_kref); |
391 | mutex_init(&isert_conn->conn_mutex); | ||
391 | 392 | ||
392 | cma_id->context = isert_conn; | 393 | cma_id->context = isert_conn; |
393 | isert_conn->conn_cm_id = cma_id; | 394 | isert_conn->conn_cm_id = cma_id; |
@@ -540,15 +541,32 @@ isert_disconnect_work(struct work_struct *work) | |||
540 | struct isert_conn, conn_logout_work); | 541 | struct isert_conn, conn_logout_work); |
541 | 542 | ||
542 | pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); | 543 | pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); |
543 | 544 | mutex_lock(&isert_conn->conn_mutex); | |
544 | isert_conn->state = ISER_CONN_DOWN; | 545 | isert_conn->state = ISER_CONN_DOWN; |
545 | 546 | ||
546 | if (isert_conn->post_recv_buf_count == 0 && | 547 | if (isert_conn->post_recv_buf_count == 0 && |
547 | atomic_read(&isert_conn->post_send_buf_count) == 0) { | 548 | atomic_read(&isert_conn->post_send_buf_count) == 0) { |
548 | pr_debug("Calling wake_up(&isert_conn->conn_wait);\n"); | 549 | pr_debug("Calling wake_up(&isert_conn->conn_wait);\n"); |
549 | wake_up(&isert_conn->conn_wait); | 550 | mutex_unlock(&isert_conn->conn_mutex); |
551 | goto wake_up; | ||
552 | } | ||
553 | if (!isert_conn->conn_cm_id) { | ||
554 | mutex_unlock(&isert_conn->conn_mutex); | ||
555 | isert_put_conn(isert_conn); | ||
556 | return; | ||
550 | } | 557 | } |
558 | if (!isert_conn->logout_posted) { | ||
559 | pr_debug("Calling rdma_disconnect for !logout_posted from" | ||
560 | " isert_disconnect_work\n"); | ||
561 | rdma_disconnect(isert_conn->conn_cm_id); | ||
562 | mutex_unlock(&isert_conn->conn_mutex); | ||
563 | iscsit_cause_connection_reinstatement(isert_conn->conn, 0); | ||
564 | goto wake_up; | ||
565 | } | ||
566 | mutex_unlock(&isert_conn->conn_mutex); | ||
551 | 567 | ||
568 | wake_up: | ||
569 | wake_up(&isert_conn->conn_wait); | ||
552 | isert_put_conn(isert_conn); | 570 | isert_put_conn(isert_conn); |
553 | } | 571 | } |
554 | 572 | ||
@@ -934,16 +952,11 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn, | |||
934 | } | 952 | } |
935 | 953 | ||
936 | sequence_cmd: | 954 | sequence_cmd: |
937 | rc = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); | 955 | rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); |
938 | 956 | ||
939 | if (!rc && dump_payload == false && unsol_data) | 957 | if (!rc && dump_payload == false && unsol_data) |
940 | iscsit_set_unsoliticed_dataout(cmd); | 958 | iscsit_set_unsoliticed_dataout(cmd); |
941 | 959 | ||
942 | if (rc == CMDSN_ERROR_CANNOT_RECOVER) | ||
943 | return iscsit_add_reject_from_cmd( | ||
944 | ISCSI_REASON_PROTOCOL_ERROR, | ||
945 | 1, 0, (unsigned char *)hdr, cmd); | ||
946 | |||
947 | return 0; | 960 | return 0; |
948 | } | 961 | } |
949 | 962 | ||
@@ -1001,17 +1014,71 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn, | |||
1001 | } | 1014 | } |
1002 | 1015 | ||
1003 | static int | 1016 | static int |
1017 | isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | ||
1018 | struct iser_rx_desc *rx_desc, unsigned char *buf) | ||
1019 | { | ||
1020 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; | ||
1021 | struct iscsi_conn *conn = isert_conn->conn; | ||
1022 | struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf; | ||
1023 | int rc; | ||
1024 | |||
1025 | rc = iscsit_setup_nop_out(conn, cmd, hdr); | ||
1026 | if (rc < 0) | ||
1027 | return rc; | ||
1028 | /* | ||
1029 | * FIXME: Add support for NOPOUT payload using unsolicited RDMA payload | ||
1030 | */ | ||
1031 | |||
1032 | return iscsit_process_nop_out(conn, cmd, hdr); | ||
1033 | } | ||
1034 | |||
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 | ||
1004 | 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, |
1005 | uint32_t read_stag, uint64_t read_va, | 1064 | uint32_t read_stag, uint64_t read_va, |
1006 | uint32_t write_stag, uint64_t write_va) | 1065 | uint32_t write_stag, uint64_t write_va) |
1007 | { | 1066 | { |
1008 | struct iscsi_hdr *hdr = &rx_desc->iscsi_header; | 1067 | struct iscsi_hdr *hdr = &rx_desc->iscsi_header; |
1009 | struct iscsi_conn *conn = isert_conn->conn; | 1068 | struct iscsi_conn *conn = isert_conn->conn; |
1069 | struct iscsi_session *sess = conn->sess; | ||
1010 | struct iscsi_cmd *cmd; | 1070 | struct iscsi_cmd *cmd; |
1011 | struct isert_cmd *isert_cmd; | 1071 | struct isert_cmd *isert_cmd; |
1012 | int ret = -EINVAL; | 1072 | int ret = -EINVAL; |
1013 | u8 opcode = (hdr->opcode & ISCSI_OPCODE_MASK); | 1073 | u8 opcode = (hdr->opcode & ISCSI_OPCODE_MASK); |
1014 | 1074 | ||
1075 | if (sess->sess_ops->SessionType && | ||
1076 | (!(opcode & ISCSI_OP_TEXT) || !(opcode & ISCSI_OP_LOGOUT))) { | ||
1077 | pr_err("Got illegal opcode: 0x%02x in SessionType=Discovery," | ||
1078 | " ignoring\n", opcode); | ||
1079 | return 0; | ||
1080 | } | ||
1081 | |||
1015 | switch (opcode) { | 1082 | switch (opcode) { |
1016 | case ISCSI_OP_SCSI_CMD: | 1083 | case ISCSI_OP_SCSI_CMD: |
1017 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 1084 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |
@@ -1032,7 +1099,9 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | |||
1032 | if (!cmd) | 1099 | if (!cmd) |
1033 | break; | 1100 | break; |
1034 | 1101 | ||
1035 | ret = iscsit_handle_nop_out(conn, cmd, (unsigned char *)hdr); | 1102 | isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd); |
1103 | ret = isert_handle_nop_out(isert_conn, isert_cmd, | ||
1104 | rx_desc, (unsigned char *)hdr); | ||
1036 | break; | 1105 | break; |
1037 | case ISCSI_OP_SCSI_DATA_OUT: | 1106 | case ISCSI_OP_SCSI_DATA_OUT: |
1038 | ret = isert_handle_iscsi_dataout(isert_conn, rx_desc, | 1107 | ret = isert_handle_iscsi_dataout(isert_conn, rx_desc, |
@@ -1057,6 +1126,15 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | |||
1057 | SECONDS_FOR_LOGOUT_COMP * | 1126 | SECONDS_FOR_LOGOUT_COMP * |
1058 | HZ); | 1127 | HZ); |
1059 | break; | 1128 | break; |
1129 | case ISCSI_OP_TEXT: | ||
1130 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | ||
1131 | if (!cmd) | ||
1132 | break; | ||
1133 | |||
1134 | isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd); | ||
1135 | ret = isert_handle_text_cmd(isert_conn, isert_cmd, | ||
1136 | rx_desc, (struct iscsi_text *)hdr); | ||
1137 | break; | ||
1060 | default: | 1138 | default: |
1061 | pr_err("Got unknown iSCSI OpCode: 0x%02x\n", opcode); | 1139 | pr_err("Got unknown iSCSI OpCode: 0x%02x\n", opcode); |
1062 | dump_stack(); | 1140 | dump_stack(); |
@@ -1184,14 +1262,12 @@ isert_put_cmd(struct isert_cmd *isert_cmd) | |||
1184 | { | 1262 | { |
1185 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; | 1263 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; |
1186 | struct isert_conn *isert_conn = isert_cmd->conn; | 1264 | struct isert_conn *isert_conn = isert_cmd->conn; |
1187 | struct iscsi_conn *conn; | 1265 | struct iscsi_conn *conn = isert_conn->conn; |
1188 | 1266 | ||
1189 | pr_debug("Entering isert_put_cmd: %p\n", isert_cmd); | 1267 | pr_debug("Entering isert_put_cmd: %p\n", isert_cmd); |
1190 | 1268 | ||
1191 | switch (cmd->iscsi_opcode) { | 1269 | switch (cmd->iscsi_opcode) { |
1192 | case ISCSI_OP_SCSI_CMD: | 1270 | case ISCSI_OP_SCSI_CMD: |
1193 | conn = isert_conn->conn; | ||
1194 | |||
1195 | spin_lock_bh(&conn->cmd_lock); | 1271 | spin_lock_bh(&conn->cmd_lock); |
1196 | if (!list_empty(&cmd->i_conn_node)) | 1272 | if (!list_empty(&cmd->i_conn_node)) |
1197 | list_del(&cmd->i_conn_node); | 1273 | list_del(&cmd->i_conn_node); |
@@ -1201,16 +1277,19 @@ isert_put_cmd(struct isert_cmd *isert_cmd) | |||
1201 | iscsit_stop_dataout_timer(cmd); | 1277 | iscsit_stop_dataout_timer(cmd); |
1202 | 1278 | ||
1203 | isert_unmap_cmd(isert_cmd, isert_conn); | 1279 | isert_unmap_cmd(isert_cmd, isert_conn); |
1204 | /* | 1280 | transport_generic_free_cmd(&cmd->se_cmd, 0); |
1205 | * Fall-through | 1281 | break; |
1206 | */ | ||
1207 | case ISCSI_OP_SCSI_TMFUNC: | 1282 | case ISCSI_OP_SCSI_TMFUNC: |
1283 | spin_lock_bh(&conn->cmd_lock); | ||
1284 | if (!list_empty(&cmd->i_conn_node)) | ||
1285 | list_del(&cmd->i_conn_node); | ||
1286 | spin_unlock_bh(&conn->cmd_lock); | ||
1287 | |||
1208 | transport_generic_free_cmd(&cmd->se_cmd, 0); | 1288 | transport_generic_free_cmd(&cmd->se_cmd, 0); |
1209 | break; | 1289 | break; |
1210 | case ISCSI_OP_REJECT: | 1290 | case ISCSI_OP_REJECT: |
1211 | case ISCSI_OP_NOOP_OUT: | 1291 | case ISCSI_OP_NOOP_OUT: |
1212 | conn = isert_conn->conn; | 1292 | case ISCSI_OP_TEXT: |
1213 | |||
1214 | spin_lock_bh(&conn->cmd_lock); | 1293 | spin_lock_bh(&conn->cmd_lock); |
1215 | if (!list_empty(&cmd->i_conn_node)) | 1294 | if (!list_empty(&cmd->i_conn_node)) |
1216 | list_del(&cmd->i_conn_node); | 1295 | list_del(&cmd->i_conn_node); |
@@ -1222,6 +1301,9 @@ isert_put_cmd(struct isert_cmd *isert_cmd) | |||
1222 | * associated cmd->se_cmd needs to be released. | 1301 | * associated cmd->se_cmd needs to be released. |
1223 | */ | 1302 | */ |
1224 | if (cmd->se_cmd.se_tfo != NULL) { | 1303 | if (cmd->se_cmd.se_tfo != NULL) { |
1304 | pr_debug("Calling transport_generic_free_cmd from" | ||
1305 | " isert_put_cmd for 0x%02x\n", | ||
1306 | cmd->iscsi_opcode); | ||
1225 | transport_generic_free_cmd(&cmd->se_cmd, 0); | 1307 | transport_generic_free_cmd(&cmd->se_cmd, 0); |
1226 | break; | 1308 | break; |
1227 | } | 1309 | } |
@@ -1249,11 +1331,11 @@ static void | |||
1249 | isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, | 1331 | isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, |
1250 | struct ib_device *ib_dev) | 1332 | struct ib_device *ib_dev) |
1251 | { | 1333 | { |
1252 | if (isert_cmd->sense_buf_dma != 0) { | 1334 | if (isert_cmd->pdu_buf_dma != 0) { |
1253 | pr_debug("Calling ib_dma_unmap_single for isert_cmd->sense_buf_dma\n"); | 1335 | pr_debug("Calling ib_dma_unmap_single for isert_cmd->pdu_buf_dma\n"); |
1254 | ib_dma_unmap_single(ib_dev, isert_cmd->sense_buf_dma, | 1336 | ib_dma_unmap_single(ib_dev, isert_cmd->pdu_buf_dma, |
1255 | isert_cmd->sense_buf_len, DMA_TO_DEVICE); | 1337 | isert_cmd->pdu_buf_len, DMA_TO_DEVICE); |
1256 | isert_cmd->sense_buf_dma = 0; | 1338 | isert_cmd->pdu_buf_dma = 0; |
1257 | } | 1339 | } |
1258 | 1340 | ||
1259 | isert_unmap_tx_desc(tx_desc, ib_dev); | 1341 | isert_unmap_tx_desc(tx_desc, ib_dev); |
@@ -1318,8 +1400,8 @@ isert_do_control_comp(struct work_struct *work) | |||
1318 | atomic_dec(&isert_conn->post_send_buf_count); | 1400 | atomic_dec(&isert_conn->post_send_buf_count); |
1319 | 1401 | ||
1320 | cmd->i_state = ISTATE_SENT_STATUS; | 1402 | cmd->i_state = ISTATE_SENT_STATUS; |
1321 | complete(&cmd->reject_comp); | ||
1322 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); | 1403 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); |
1404 | break; | ||
1323 | case ISTATE_SEND_LOGOUTRSP: | 1405 | case ISTATE_SEND_LOGOUTRSP: |
1324 | pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); | 1406 | pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); |
1325 | /* | 1407 | /* |
@@ -1329,6 +1411,11 @@ isert_do_control_comp(struct work_struct *work) | |||
1329 | isert_conn->logout_posted = true; | 1411 | isert_conn->logout_posted = true; |
1330 | iscsit_logout_post_handler(cmd, cmd->conn); | 1412 | iscsit_logout_post_handler(cmd, cmd->conn); |
1331 | break; | 1413 | break; |
1414 | case ISTATE_SEND_TEXTRSP: | ||
1415 | atomic_dec(&isert_conn->post_send_buf_count); | ||
1416 | cmd->i_state = ISTATE_SENT_STATUS; | ||
1417 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); | ||
1418 | break; | ||
1332 | default: | 1419 | default: |
1333 | pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state); | 1420 | pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state); |
1334 | dump_stack(); | 1421 | dump_stack(); |
@@ -1345,7 +1432,9 @@ isert_response_completion(struct iser_tx_desc *tx_desc, | |||
1345 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; | 1432 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; |
1346 | 1433 | ||
1347 | if (cmd->i_state == ISTATE_SEND_TASKMGTRSP || | 1434 | if (cmd->i_state == ISTATE_SEND_TASKMGTRSP || |
1348 | cmd->i_state == ISTATE_SEND_LOGOUTRSP) { | 1435 | cmd->i_state == ISTATE_SEND_LOGOUTRSP || |
1436 | cmd->i_state == ISTATE_SEND_REJECT || | ||
1437 | cmd->i_state == ISTATE_SEND_TEXTRSP) { | ||
1349 | isert_unmap_tx_desc(tx_desc, ib_dev); | 1438 | isert_unmap_tx_desc(tx_desc, ib_dev); |
1350 | 1439 | ||
1351 | INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp); | 1440 | INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp); |
@@ -1419,7 +1508,11 @@ isert_cq_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn) | |||
1419 | pr_debug("isert_cq_comp_err >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); | 1508 | pr_debug("isert_cq_comp_err >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); |
1420 | pr_debug("Calling wake_up from isert_cq_comp_err\n"); | 1509 | pr_debug("Calling wake_up from isert_cq_comp_err\n"); |
1421 | 1510 | ||
1422 | isert_conn->state = ISER_CONN_TERMINATING; | 1511 | mutex_lock(&isert_conn->conn_mutex); |
1512 | if (isert_conn->state != ISER_CONN_DOWN) | ||
1513 | isert_conn->state = ISER_CONN_TERMINATING; | ||
1514 | mutex_unlock(&isert_conn->conn_mutex); | ||
1515 | |||
1423 | wake_up(&isert_conn->conn_wait_comp_err); | 1516 | wake_up(&isert_conn->conn_wait_comp_err); |
1424 | } | 1517 | } |
1425 | } | 1518 | } |
@@ -1445,6 +1538,7 @@ isert_cq_tx_work(struct work_struct *work) | |||
1445 | } else { | 1538 | } else { |
1446 | pr_debug("TX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); | 1539 | pr_debug("TX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); |
1447 | pr_debug("TX wc.status: 0x%08x\n", wc.status); | 1540 | pr_debug("TX wc.status: 0x%08x\n", wc.status); |
1541 | pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err); | ||
1448 | atomic_dec(&isert_conn->post_send_buf_count); | 1542 | atomic_dec(&isert_conn->post_send_buf_count); |
1449 | isert_cq_comp_err(tx_desc, isert_conn); | 1543 | isert_cq_comp_err(tx_desc, isert_conn); |
1450 | } | 1544 | } |
@@ -1484,9 +1578,11 @@ isert_cq_rx_work(struct work_struct *work) | |||
1484 | isert_rx_completion(rx_desc, isert_conn, xfer_len); | 1578 | isert_rx_completion(rx_desc, isert_conn, xfer_len); |
1485 | } else { | 1579 | } else { |
1486 | pr_debug("RX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); | 1580 | pr_debug("RX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); |
1487 | if (wc.status != IB_WC_WR_FLUSH_ERR) | 1581 | if (wc.status != IB_WC_WR_FLUSH_ERR) { |
1488 | pr_debug("RX wc.status: 0x%08x\n", wc.status); | 1582 | pr_debug("RX wc.status: 0x%08x\n", wc.status); |
1489 | 1583 | pr_debug("RX wc.vendor_err: 0x%08x\n", | |
1584 | wc.vendor_err); | ||
1585 | } | ||
1490 | isert_conn->post_recv_buf_count--; | 1586 | isert_conn->post_recv_buf_count--; |
1491 | isert_cq_comp_err(NULL, isert_conn); | 1587 | isert_cq_comp_err(NULL, isert_conn); |
1492 | } | 1588 | } |
@@ -1543,7 +1639,7 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd) | |||
1543 | (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) { | 1639 | (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) { |
1544 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 1640 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; |
1545 | struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; | 1641 | struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; |
1546 | u32 padding, sense_len; | 1642 | u32 padding, pdu_len; |
1547 | 1643 | ||
1548 | put_unaligned_be16(cmd->se_cmd.scsi_sense_length, | 1644 | put_unaligned_be16(cmd->se_cmd.scsi_sense_length, |
1549 | cmd->sense_buffer); | 1645 | cmd->sense_buffer); |
@@ -1551,15 +1647,15 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd) | |||
1551 | 1647 | ||
1552 | padding = -(cmd->se_cmd.scsi_sense_length) & 3; | 1648 | padding = -(cmd->se_cmd.scsi_sense_length) & 3; |
1553 | hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length); | 1649 | hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length); |
1554 | sense_len = cmd->se_cmd.scsi_sense_length + padding; | 1650 | pdu_len = cmd->se_cmd.scsi_sense_length + padding; |
1555 | 1651 | ||
1556 | isert_cmd->sense_buf_dma = ib_dma_map_single(ib_dev, | 1652 | isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, |
1557 | (void *)cmd->sense_buffer, sense_len, | 1653 | (void *)cmd->sense_buffer, pdu_len, |
1558 | DMA_TO_DEVICE); | 1654 | DMA_TO_DEVICE); |
1559 | 1655 | ||
1560 | isert_cmd->sense_buf_len = sense_len; | 1656 | isert_cmd->pdu_buf_len = pdu_len; |
1561 | tx_dsg->addr = isert_cmd->sense_buf_dma; | 1657 | tx_dsg->addr = isert_cmd->pdu_buf_dma; |
1562 | tx_dsg->length = sense_len; | 1658 | tx_dsg->length = pdu_len; |
1563 | tx_dsg->lkey = isert_conn->conn_mr->lkey; | 1659 | tx_dsg->lkey = isert_conn->conn_mr->lkey; |
1564 | isert_cmd->tx_desc.num_sge = 2; | 1660 | isert_cmd->tx_desc.num_sge = 2; |
1565 | } | 1661 | } |
@@ -1637,11 +1733,25 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | |||
1637 | struct isert_cmd, iscsi_cmd); | 1733 | struct isert_cmd, iscsi_cmd); |
1638 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 1734 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; |
1639 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | 1735 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; |
1736 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | ||
1737 | struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; | ||
1738 | struct iscsi_reject *hdr = | ||
1739 | (struct iscsi_reject *)&isert_cmd->tx_desc.iscsi_header; | ||
1640 | 1740 | ||
1641 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | 1741 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); |
1642 | iscsit_build_reject(cmd, conn, (struct iscsi_reject *) | 1742 | iscsit_build_reject(cmd, conn, hdr); |
1643 | &isert_cmd->tx_desc.iscsi_header); | ||
1644 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | 1743 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); |
1744 | |||
1745 | hton24(hdr->dlength, ISCSI_HDR_LEN); | ||
1746 | isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, | ||
1747 | (void *)cmd->buf_ptr, ISCSI_HDR_LEN, | ||
1748 | DMA_TO_DEVICE); | ||
1749 | isert_cmd->pdu_buf_len = ISCSI_HDR_LEN; | ||
1750 | tx_dsg->addr = isert_cmd->pdu_buf_dma; | ||
1751 | tx_dsg->length = ISCSI_HDR_LEN; | ||
1752 | tx_dsg->lkey = isert_conn->conn_mr->lkey; | ||
1753 | isert_cmd->tx_desc.num_sge = 2; | ||
1754 | |||
1645 | isert_init_send_wr(isert_cmd, send_wr); | 1755 | isert_init_send_wr(isert_cmd, send_wr); |
1646 | 1756 | ||
1647 | pr_debug("Posting Reject IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | 1757 | pr_debug("Posting Reject IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); |
@@ -1650,6 +1760,47 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | |||
1650 | } | 1760 | } |
1651 | 1761 | ||
1652 | static int | 1762 | static int |
1763 | isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | ||
1764 | { | ||
1765 | struct isert_cmd *isert_cmd = container_of(cmd, | ||
1766 | struct isert_cmd, iscsi_cmd); | ||
1767 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | ||
1768 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | ||
1769 | struct iscsi_text_rsp *hdr = | ||
1770 | (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header; | ||
1771 | u32 txt_rsp_len; | ||
1772 | int rc; | ||
1773 | |||
1774 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | ||
1775 | rc = iscsit_build_text_rsp(cmd, conn, hdr); | ||
1776 | if (rc < 0) | ||
1777 | return rc; | ||
1778 | |||
1779 | txt_rsp_len = rc; | ||
1780 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | ||
1781 | |||
1782 | if (txt_rsp_len) { | ||
1783 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | ||
1784 | struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; | ||
1785 | void *txt_rsp_buf = cmd->buf_ptr; | ||
1786 | |||
1787 | isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, | ||
1788 | txt_rsp_buf, txt_rsp_len, DMA_TO_DEVICE); | ||
1789 | |||
1790 | isert_cmd->pdu_buf_len = txt_rsp_len; | ||
1791 | tx_dsg->addr = isert_cmd->pdu_buf_dma; | ||
1792 | tx_dsg->length = txt_rsp_len; | ||
1793 | tx_dsg->lkey = isert_conn->conn_mr->lkey; | ||
1794 | isert_cmd->tx_desc.num_sge = 2; | ||
1795 | } | ||
1796 | isert_init_send_wr(isert_cmd, send_wr); | ||
1797 | |||
1798 | pr_debug("Posting Text Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | ||
1799 | |||
1800 | return isert_post_response(isert_conn, isert_cmd); | ||
1801 | } | ||
1802 | |||
1803 | static int | ||
1653 | isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | 1804 | isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, |
1654 | struct ib_sge *ib_sge, struct ib_send_wr *send_wr, | 1805 | struct ib_sge *ib_sge, struct ib_send_wr *send_wr, |
1655 | u32 data_left, u32 offset) | 1806 | u32 data_left, u32 offset) |
@@ -1947,6 +2098,9 @@ isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) | |||
1947 | case ISTATE_SEND_REJECT: | 2098 | case ISTATE_SEND_REJECT: |
1948 | ret = isert_put_reject(cmd, conn); | 2099 | ret = isert_put_reject(cmd, conn); |
1949 | break; | 2100 | break; |
2101 | case ISTATE_SEND_TEXTRSP: | ||
2102 | ret = isert_put_text_rsp(cmd, conn); | ||
2103 | break; | ||
1950 | case ISTATE_SEND_STATUS: | 2104 | case ISTATE_SEND_STATUS: |
1951 | /* | 2105 | /* |
1952 | * Special case for sending non GOOD SCSI status from TX thread | 2106 | * Special case for sending non GOOD SCSI status from TX thread |
@@ -2175,6 +2329,17 @@ isert_free_np(struct iscsi_np *np) | |||
2175 | kfree(isert_np); | 2329 | kfree(isert_np); |
2176 | } | 2330 | } |
2177 | 2331 | ||
2332 | static int isert_check_state(struct isert_conn *isert_conn, int state) | ||
2333 | { | ||
2334 | int ret; | ||
2335 | |||
2336 | mutex_lock(&isert_conn->conn_mutex); | ||
2337 | ret = (isert_conn->state == state); | ||
2338 | mutex_unlock(&isert_conn->conn_mutex); | ||
2339 | |||
2340 | return ret; | ||
2341 | } | ||
2342 | |||
2178 | static void isert_free_conn(struct iscsi_conn *conn) | 2343 | static void isert_free_conn(struct iscsi_conn *conn) |
2179 | { | 2344 | { |
2180 | struct isert_conn *isert_conn = conn->context; | 2345 | struct isert_conn *isert_conn = conn->context; |
@@ -2184,26 +2349,43 @@ static void isert_free_conn(struct iscsi_conn *conn) | |||
2184 | * Decrement post_send_buf_count for special case when called | 2349 | * Decrement post_send_buf_count for special case when called |
2185 | * from isert_do_control_comp() -> iscsit_logout_post_handler() | 2350 | * from isert_do_control_comp() -> iscsit_logout_post_handler() |
2186 | */ | 2351 | */ |
2352 | mutex_lock(&isert_conn->conn_mutex); | ||
2187 | if (isert_conn->logout_posted) | 2353 | if (isert_conn->logout_posted) |
2188 | atomic_dec(&isert_conn->post_send_buf_count); | 2354 | atomic_dec(&isert_conn->post_send_buf_count); |
2189 | 2355 | ||
2190 | if (isert_conn->conn_cm_id) | 2356 | if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) { |
2357 | pr_debug("Calling rdma_disconnect from isert_free_conn\n"); | ||
2191 | rdma_disconnect(isert_conn->conn_cm_id); | 2358 | rdma_disconnect(isert_conn->conn_cm_id); |
2359 | } | ||
2192 | /* | 2360 | /* |
2193 | * Only wait for conn_wait_comp_err if the isert_conn made it | 2361 | * Only wait for conn_wait_comp_err if the isert_conn made it |
2194 | * into full feature phase.. | 2362 | * into full feature phase.. |
2195 | */ | 2363 | */ |
2196 | if (isert_conn->state > ISER_CONN_INIT) { | 2364 | if (isert_conn->state == ISER_CONN_UP) { |
2197 | pr_debug("isert_free_conn: Before wait_event comp_err %d\n", | 2365 | pr_debug("isert_free_conn: Before wait_event comp_err %d\n", |
2198 | isert_conn->state); | 2366 | isert_conn->state); |
2367 | mutex_unlock(&isert_conn->conn_mutex); | ||
2368 | |||
2199 | wait_event(isert_conn->conn_wait_comp_err, | 2369 | wait_event(isert_conn->conn_wait_comp_err, |
2200 | isert_conn->state == ISER_CONN_TERMINATING); | 2370 | (isert_check_state(isert_conn, ISER_CONN_TERMINATING))); |
2201 | pr_debug("isert_free_conn: After wait_event #1 >>>>>>>>>>>>\n"); | 2371 | |
2372 | wait_event(isert_conn->conn_wait, | ||
2373 | (isert_check_state(isert_conn, ISER_CONN_DOWN))); | ||
2374 | |||
2375 | isert_put_conn(isert_conn); | ||
2376 | return; | ||
2377 | } | ||
2378 | if (isert_conn->state == ISER_CONN_INIT) { | ||
2379 | mutex_unlock(&isert_conn->conn_mutex); | ||
2380 | isert_put_conn(isert_conn); | ||
2381 | return; | ||
2202 | } | 2382 | } |
2383 | pr_debug("isert_free_conn: wait_event conn_wait %d\n", | ||
2384 | isert_conn->state); | ||
2385 | mutex_unlock(&isert_conn->conn_mutex); | ||
2203 | 2386 | ||
2204 | pr_debug("isert_free_conn: wait_event conn_wait %d\n", isert_conn->state); | 2387 | wait_event(isert_conn->conn_wait, |
2205 | wait_event(isert_conn->conn_wait, isert_conn->state == ISER_CONN_DOWN); | 2388 | (isert_check_state(isert_conn, ISER_CONN_DOWN))); |
2206 | pr_debug("isert_free_conn: After wait_event #2 >>>>>>>>>>>>>>>>>>>>\n"); | ||
2207 | 2389 | ||
2208 | isert_put_conn(isert_conn); | 2390 | isert_put_conn(isert_conn); |
2209 | } | 2391 | } |
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index b104f4c2cd38..191117b5b508 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h | |||
@@ -61,8 +61,8 @@ struct isert_cmd { | |||
61 | uint32_t write_stag; | 61 | uint32_t write_stag; |
62 | uint64_t read_va; | 62 | uint64_t read_va; |
63 | uint64_t write_va; | 63 | uint64_t write_va; |
64 | u64 sense_buf_dma; | 64 | u64 pdu_buf_dma; |
65 | u32 sense_buf_len; | 65 | u32 pdu_buf_len; |
66 | u32 read_va_off; | 66 | u32 read_va_off; |
67 | u32 write_va_off; | 67 | u32 write_va_off; |
68 | u32 rdma_wr_num; | 68 | u32 rdma_wr_num; |
@@ -102,6 +102,7 @@ struct isert_conn { | |||
102 | struct ib_qp *conn_qp; | 102 | struct ib_qp *conn_qp; |
103 | struct isert_device *conn_device; | 103 | struct isert_device *conn_device; |
104 | struct work_struct conn_logout_work; | 104 | struct work_struct conn_logout_work; |
105 | struct mutex conn_mutex; | ||
105 | wait_queue_head_t conn_wait; | 106 | wait_queue_head_t conn_wait; |
106 | wait_queue_head_t conn_wait_comp_err; | 107 | wait_queue_head_t conn_wait_comp_err; |
107 | struct kref conn_kref; | 108 | struct kref conn_kref; |