aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-05-21 16:54:05 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-12 09:22:18 -0400
commit052d014485d2ce5bb7fa8dd0df875dafd1db77df (patch)
tree9bbbe1487e5263db24d69b69df99a4603d4b00d6 /drivers/scsi/libiscsi.c
parent0af967f5d4f2dd1e00618d34ac988037d37a6c3b (diff)
[SCSI] libiscsi: modify libiscsi so it supports offloaded data paths
This patch modifies libiscsi, so drivers like bnx2i and iser can execute a command from queuecommand/send_pdu instead of having to be queued to be run in a workq. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c179
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}
87EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); 89EXPORT_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
340static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask) 348static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask)
@@ -403,6 +411,50 @@ void iscsi_free_mgmt_task(struct iscsi_conn *conn,
403} 411}
404EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task); 412EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
405 413
414static 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
406static struct iscsi_mgmt_task * 458static 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}
460EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); 530EXPORT_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
597static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, 658static 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}
869EXPORT_SYMBOL_GPL(iscsi_conn_failure); 930EXPORT_SYMBOL_GPL(iscsi_conn_failure);
870 931
871static 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
907static int iscsi_xmit_mtask(struct iscsi_conn *conn) 932static 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 */
966void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask) 987void 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,
1412void iscsi_suspend_tx(struct iscsi_conn *conn) 1439void 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}
1417EXPORT_SYMBOL_GPL(iscsi_suspend_tx); 1445EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
1418 1446
1419static void iscsi_start_tx(struct iscsi_conn *conn) 1447static 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
1425static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) 1454static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)