diff options
Diffstat (limited to 'drivers/scsi')
| -rw-r--r-- | drivers/scsi/libiscsi.c | 179 |
1 files changed, 104 insertions, 75 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 4bc63c4b3c10..1e605de07cff 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
| @@ -79,9 +79,11 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | |||
| 79 | * xmit thread | 79 | * xmit thread |
| 80 | */ | 80 | */ |
| 81 | if (!list_empty(&session->leadconn->xmitqueue) || | 81 | if (!list_empty(&session->leadconn->xmitqueue) || |
| 82 | !list_empty(&session->leadconn->mgmtqueue)) | 82 | !list_empty(&session->leadconn->mgmtqueue)) { |
| 83 | scsi_queue_work(session->host, | 83 | if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
| 84 | &session->leadconn->xmitwork); | 84 | scsi_queue_work(session->host, |
| 85 | &session->leadconn->xmitwork); | ||
| 86 | } | ||
| 85 | } | 87 | } |
| 86 | } | 88 | } |
| 87 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); | 89 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); |
| @@ -298,8 +300,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) | |||
| 298 | WARN_ON(hdrlength >= 256); | 300 | WARN_ON(hdrlength >= 256); |
| 299 | hdr->hlength = hdrlength & 0xFF; | 301 | hdr->hlength = hdrlength & 0xFF; |
| 300 | 302 | ||
| 301 | if (conn->session->tt->init_cmd_task(conn->ctask)) | 303 | if (conn->session->tt->init_cmd_task && |
| 302 | return EIO; | 304 | conn->session->tt->init_cmd_task(ctask)) |
| 305 | return -EIO; | ||
| 306 | |||
| 307 | ctask->state = ISCSI_TASK_RUNNING; | ||
| 308 | list_move_tail(&ctask->running, &conn->run_list); | ||
| 303 | 309 | ||
| 304 | conn->scsicmd_pdus_cnt++; | 310 | conn->scsicmd_pdus_cnt++; |
| 305 | debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x " | 311 | debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x " |
| @@ -334,7 +340,9 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask) | |||
| 334 | conn->ctask = NULL; | 340 | conn->ctask = NULL; |
| 335 | list_del_init(&ctask->running); | 341 | list_del_init(&ctask->running); |
| 336 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); | 342 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); |
| 337 | sc->scsi_done(sc); | 343 | |
| 344 | if (sc->scsi_done) | ||
| 345 | sc->scsi_done(sc); | ||
| 338 | } | 346 | } |
| 339 | 347 | ||
| 340 | static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask) | 348 | static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask) |
| @@ -403,6 +411,50 @@ void iscsi_free_mgmt_task(struct iscsi_conn *conn, | |||
| 403 | } | 411 | } |
| 404 | EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task); | 412 | EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task); |
| 405 | 413 | ||
| 414 | static int iscsi_prep_mtask(struct iscsi_conn *conn, | ||
| 415 | struct iscsi_mgmt_task *mtask) | ||
| 416 | { | ||
| 417 | struct iscsi_session *session = conn->session; | ||
| 418 | struct iscsi_hdr *hdr = mtask->hdr; | ||
| 419 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; | ||
| 420 | |||
| 421 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) | ||
| 422 | return -ENOTCONN; | ||
| 423 | |||
| 424 | if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) && | ||
| 425 | hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) | ||
| 426 | nop->exp_statsn = cpu_to_be32(conn->exp_statsn); | ||
| 427 | /* | ||
| 428 | * pre-format CmdSN for outgoing PDU. | ||
| 429 | */ | ||
| 430 | nop->cmdsn = cpu_to_be32(session->cmdsn); | ||
| 431 | if (hdr->itt != RESERVED_ITT) { | ||
| 432 | hdr->itt = build_itt(mtask->itt, session->age); | ||
| 433 | /* | ||
| 434 | * TODO: We always use immediate, so we never hit this. | ||
| 435 | * If we start to send tmfs or nops as non-immediate then | ||
| 436 | * we should start checking the cmdsn numbers for mgmt tasks. | ||
| 437 | */ | ||
| 438 | if (conn->c_stage == ISCSI_CONN_STARTED && | ||
| 439 | !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | ||
| 440 | session->queued_cmdsn++; | ||
| 441 | session->cmdsn++; | ||
| 442 | } | ||
| 443 | } | ||
| 444 | |||
| 445 | if (session->tt->init_mgmt_task) | ||
| 446 | session->tt->init_mgmt_task(conn, mtask); | ||
| 447 | |||
| 448 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) | ||
| 449 | session->state = ISCSI_STATE_LOGGING_OUT; | ||
| 450 | |||
| 451 | list_move_tail(&mtask->running, &conn->mgmt_run_list); | ||
| 452 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", | ||
| 453 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, | ||
| 454 | mtask->data_count); | ||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 406 | static struct iscsi_mgmt_task * | 458 | static struct iscsi_mgmt_task * |
| 407 | __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 459 | __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
| 408 | char *data, uint32_t data_size) | 460 | char *data, uint32_t data_size) |
| @@ -429,6 +481,12 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 429 | if (!__kfifo_get(session->mgmtpool.queue, | 481 | if (!__kfifo_get(session->mgmtpool.queue, |
| 430 | (void*)&mtask, sizeof(void*))) | 482 | (void*)&mtask, sizeof(void*))) |
| 431 | return NULL; | 483 | return NULL; |
| 484 | |||
| 485 | if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) && | ||
| 486 | hdr->ttt == RESERVED_ITT) { | ||
| 487 | conn->ping_mtask = mtask; | ||
| 488 | conn->last_ping = jiffies; | ||
| 489 | } | ||
| 432 | } | 490 | } |
| 433 | 491 | ||
| 434 | if (data_size) { | 492 | if (data_size) { |
| @@ -440,6 +498,19 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 440 | memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); | 498 | memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); |
| 441 | INIT_LIST_HEAD(&mtask->running); | 499 | INIT_LIST_HEAD(&mtask->running); |
| 442 | list_add_tail(&mtask->running, &conn->mgmtqueue); | 500 | list_add_tail(&mtask->running, &conn->mgmtqueue); |
| 501 | |||
| 502 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | ||
| 503 | if (iscsi_prep_mtask(conn, mtask)) { | ||
| 504 | iscsi_free_mgmt_task(conn, mtask); | ||
| 505 | return NULL; | ||
| 506 | } | ||
| 507 | |||
| 508 | if (session->tt->xmit_mgmt_task(conn, mtask)) | ||
| 509 | mtask = NULL; | ||
| 510 | |||
| 511 | } else | ||
| 512 | scsi_queue_work(conn->session->host, &conn->xmitwork); | ||
| 513 | |||
| 443 | return mtask; | 514 | return mtask; |
| 444 | } | 515 | } |
| 445 | 516 | ||
| @@ -454,7 +525,6 @@ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, | |||
| 454 | if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size)) | 525 | if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size)) |
| 455 | err = -EPERM; | 526 | err = -EPERM; |
| 456 | spin_unlock_bh(&session->lock); | 527 | spin_unlock_bh(&session->lock); |
| 457 | scsi_queue_work(session->host, &conn->xmitwork); | ||
| 458 | return err; | 528 | return err; |
| 459 | } | 529 | } |
| 460 | EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); | 530 | EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); |
| @@ -581,17 +651,8 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) | |||
| 581 | hdr.ttt = RESERVED_ITT; | 651 | hdr.ttt = RESERVED_ITT; |
| 582 | 652 | ||
| 583 | mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); | 653 | mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); |
| 584 | if (!mtask) { | 654 | if (!mtask) |
| 585 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); | 655 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); |
| 586 | return; | ||
| 587 | } | ||
| 588 | |||
| 589 | /* only track our nops */ | ||
| 590 | if (!rhdr) { | ||
| 591 | conn->ping_mtask = mtask; | ||
| 592 | conn->last_ping = jiffies; | ||
| 593 | } | ||
| 594 | scsi_queue_work(conn->session->host, &conn->xmitwork); | ||
| 595 | } | 656 | } |
| 596 | 657 | ||
| 597 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 658 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
| @@ -868,56 +929,15 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) | |||
| 868 | } | 929 | } |
| 869 | EXPORT_SYMBOL_GPL(iscsi_conn_failure); | 930 | EXPORT_SYMBOL_GPL(iscsi_conn_failure); |
| 870 | 931 | ||
| 871 | static void iscsi_prep_mtask(struct iscsi_conn *conn, | ||
| 872 | struct iscsi_mgmt_task *mtask) | ||
| 873 | { | ||
| 874 | struct iscsi_session *session = conn->session; | ||
| 875 | struct iscsi_hdr *hdr = mtask->hdr; | ||
| 876 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; | ||
| 877 | |||
| 878 | if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) && | ||
| 879 | hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) | ||
| 880 | nop->exp_statsn = cpu_to_be32(conn->exp_statsn); | ||
| 881 | /* | ||
| 882 | * pre-format CmdSN for outgoing PDU. | ||
| 883 | */ | ||
| 884 | nop->cmdsn = cpu_to_be32(session->cmdsn); | ||
| 885 | if (hdr->itt != RESERVED_ITT) { | ||
| 886 | hdr->itt = build_itt(mtask->itt, session->age); | ||
| 887 | /* | ||
| 888 | * TODO: We always use immediate, so we never hit this. | ||
| 889 | * If we start to send tmfs or nops as non-immediate then | ||
| 890 | * we should start checking the cmdsn numbers for mgmt tasks. | ||
| 891 | */ | ||
| 892 | if (conn->c_stage == ISCSI_CONN_STARTED && | ||
| 893 | !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | ||
| 894 | session->queued_cmdsn++; | ||
| 895 | session->cmdsn++; | ||
| 896 | } | ||
| 897 | } | ||
| 898 | |||
| 899 | if (session->tt->init_mgmt_task) | ||
| 900 | session->tt->init_mgmt_task(conn, mtask); | ||
| 901 | |||
| 902 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", | ||
| 903 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, | ||
| 904 | mtask->data_count); | ||
| 905 | } | ||
| 906 | |||
| 907 | static int iscsi_xmit_mtask(struct iscsi_conn *conn) | 932 | static int iscsi_xmit_mtask(struct iscsi_conn *conn) |
| 908 | { | 933 | { |
| 909 | struct iscsi_hdr *hdr = conn->mtask->hdr; | ||
| 910 | int rc; | 934 | int rc; |
| 911 | 935 | ||
| 912 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) | ||
| 913 | conn->session->state = ISCSI_STATE_LOGGING_OUT; | ||
| 914 | spin_unlock_bh(&conn->session->lock); | 936 | spin_unlock_bh(&conn->session->lock); |
| 915 | |||
| 916 | rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); | 937 | rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); |
| 917 | spin_lock_bh(&conn->session->lock); | 938 | spin_lock_bh(&conn->session->lock); |
| 918 | if (rc) | 939 | if (rc) |
| 919 | return rc; | 940 | return rc; |
| 920 | |||
| 921 | /* done with this in-progress mtask */ | 941 | /* done with this in-progress mtask */ |
| 922 | conn->mtask = NULL; | 942 | conn->mtask = NULL; |
| 923 | return 0; | 943 | return 0; |
| @@ -961,7 +981,8 @@ static int iscsi_xmit_ctask(struct iscsi_conn *conn) | |||
| 961 | * @ctask: ctask to requeue | 981 | * @ctask: ctask to requeue |
| 962 | * | 982 | * |
| 963 | * LLDs that need to run a ctask from the session workqueue should call | 983 | * LLDs that need to run a ctask from the session workqueue should call |
| 964 | * this. The session lock must be held. | 984 | * this. The session lock must be held. This should only be called |
| 985 | * by software drivers. | ||
| 965 | */ | 986 | */ |
| 966 | void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask) | 987 | void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask) |
| 967 | { | 988 | { |
| @@ -1013,14 +1034,11 @@ check_mgmt: | |||
| 1013 | while (!list_empty(&conn->mgmtqueue)) { | 1034 | while (!list_empty(&conn->mgmtqueue)) { |
| 1014 | conn->mtask = list_entry(conn->mgmtqueue.next, | 1035 | conn->mtask = list_entry(conn->mgmtqueue.next, |
| 1015 | struct iscsi_mgmt_task, running); | 1036 | struct iscsi_mgmt_task, running); |
| 1016 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { | 1037 | if (iscsi_prep_mtask(conn, conn->mtask)) { |
| 1017 | iscsi_free_mgmt_task(conn, conn->mtask); | 1038 | iscsi_free_mgmt_task(conn, conn->mtask); |
| 1018 | conn->mtask = NULL; | 1039 | conn->mtask = NULL; |
| 1019 | continue; | 1040 | continue; |
| 1020 | } | 1041 | } |
| 1021 | |||
| 1022 | iscsi_prep_mtask(conn, conn->mtask); | ||
| 1023 | list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list); | ||
| 1024 | rc = iscsi_xmit_mtask(conn); | 1042 | rc = iscsi_xmit_mtask(conn); |
| 1025 | if (rc) | 1043 | if (rc) |
| 1026 | goto again; | 1044 | goto again; |
| @@ -1041,9 +1059,6 @@ check_mgmt: | |||
| 1041 | fail_command(conn, conn->ctask, DID_ABORT << 16); | 1059 | fail_command(conn, conn->ctask, DID_ABORT << 16); |
| 1042 | continue; | 1060 | continue; |
| 1043 | } | 1061 | } |
| 1044 | |||
| 1045 | conn->ctask->state = ISCSI_TASK_RUNNING; | ||
| 1046 | list_move_tail(conn->xmitqueue.next, &conn->run_list); | ||
| 1047 | rc = iscsi_xmit_ctask(conn); | 1062 | rc = iscsi_xmit_ctask(conn); |
| 1048 | if (rc) | 1063 | if (rc) |
| 1049 | goto again; | 1064 | goto again; |
| @@ -1192,8 +1207,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
| 1192 | reason = FAILURE_OOM; | 1207 | reason = FAILURE_OOM; |
| 1193 | goto reject; | 1208 | goto reject; |
| 1194 | } | 1209 | } |
| 1195 | session->queued_cmdsn++; | ||
| 1196 | |||
| 1197 | sc->SCp.phase = session->age; | 1210 | sc->SCp.phase = session->age; |
| 1198 | sc->SCp.ptr = (char *)ctask; | 1211 | sc->SCp.ptr = (char *)ctask; |
| 1199 | 1212 | ||
| @@ -1202,11 +1215,26 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
| 1202 | ctask->conn = conn; | 1215 | ctask->conn = conn; |
| 1203 | ctask->sc = sc; | 1216 | ctask->sc = sc; |
| 1204 | INIT_LIST_HEAD(&ctask->running); | 1217 | INIT_LIST_HEAD(&ctask->running); |
| 1205 | |||
| 1206 | list_add_tail(&ctask->running, &conn->xmitqueue); | 1218 | list_add_tail(&ctask->running, &conn->xmitqueue); |
| 1207 | spin_unlock(&session->lock); | ||
| 1208 | 1219 | ||
| 1209 | scsi_queue_work(host, &conn->xmitwork); | 1220 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { |
| 1221 | if (iscsi_prep_scsi_cmd_pdu(ctask)) { | ||
| 1222 | sc->result = DID_ABORT << 16; | ||
| 1223 | sc->scsi_done = NULL; | ||
| 1224 | iscsi_complete_command(ctask); | ||
| 1225 | goto fault; | ||
| 1226 | } | ||
| 1227 | if (session->tt->xmit_cmd_task(conn, ctask)) { | ||
| 1228 | sc->scsi_done = NULL; | ||
| 1229 | iscsi_complete_command(ctask); | ||
| 1230 | reason = FAILURE_SESSION_NOT_READY; | ||
| 1231 | goto reject; | ||
| 1232 | } | ||
| 1233 | } else | ||
| 1234 | scsi_queue_work(session->host, &conn->xmitwork); | ||
| 1235 | |||
| 1236 | session->queued_cmdsn++; | ||
| 1237 | spin_unlock(&session->lock); | ||
| 1210 | spin_lock(host->host_lock); | 1238 | spin_lock(host->host_lock); |
| 1211 | return 0; | 1239 | return 0; |
| 1212 | 1240 | ||
| @@ -1225,7 +1253,7 @@ fault: | |||
| 1225 | scsi_out(sc)->resid = scsi_out(sc)->length; | 1253 | scsi_out(sc)->resid = scsi_out(sc)->length; |
| 1226 | scsi_in(sc)->resid = scsi_in(sc)->length; | 1254 | scsi_in(sc)->resid = scsi_in(sc)->length; |
| 1227 | } | 1255 | } |
| 1228 | sc->scsi_done(sc); | 1256 | done(sc); |
| 1229 | spin_lock(host->host_lock); | 1257 | spin_lock(host->host_lock); |
| 1230 | return 0; | 1258 | return 0; |
| 1231 | } | 1259 | } |
| @@ -1344,7 +1372,6 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
| 1344 | 1372 | ||
| 1345 | spin_unlock_bh(&session->lock); | 1373 | spin_unlock_bh(&session->lock); |
| 1346 | mutex_unlock(&session->eh_mutex); | 1374 | mutex_unlock(&session->eh_mutex); |
| 1347 | scsi_queue_work(session->host, &conn->xmitwork); | ||
| 1348 | 1375 | ||
| 1349 | /* | 1376 | /* |
| 1350 | * block eh thread until: | 1377 | * block eh thread until: |
| @@ -1412,14 +1439,16 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, | |||
| 1412 | void iscsi_suspend_tx(struct iscsi_conn *conn) | 1439 | void iscsi_suspend_tx(struct iscsi_conn *conn) |
| 1413 | { | 1440 | { |
| 1414 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1441 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
| 1415 | scsi_flush_work(conn->session->host); | 1442 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
| 1443 | scsi_flush_work(conn->session->host); | ||
| 1416 | } | 1444 | } |
| 1417 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); | 1445 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); |
| 1418 | 1446 | ||
| 1419 | static void iscsi_start_tx(struct iscsi_conn *conn) | 1447 | static void iscsi_start_tx(struct iscsi_conn *conn) |
| 1420 | { | 1448 | { |
| 1421 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1449 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
| 1422 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 1450 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
| 1451 | scsi_queue_work(conn->session->host, &conn->xmitwork); | ||
| 1423 | } | 1452 | } |
| 1424 | 1453 | ||
| 1425 | static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | 1454 | static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) |
