diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-21 16:54:07 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:19 -0400 |
commit | fbc514b4e262bc0596faae8640ebc0b9142a1cdd (patch) | |
tree | 74910fb5c2b2475742d13f4ac44e5eddf7aad81a /drivers/scsi/iscsi_tcp.c | |
parent | 3e5c28ad0391389959ccae81c938c7533efb3490 (diff) |
[SCSI] iscsi_tcp: convert iscsi_tcp to support merged tasks
Convert iscsi_tcp to support merged tasks.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 130 |
1 files changed, 54 insertions, 76 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index f2a08f7ed902..517bad160bea 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -498,11 +498,15 @@ iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn) | |||
498 | * must be called with session lock | 498 | * must be called with session lock |
499 | */ | 499 | */ |
500 | static void | 500 | static void |
501 | iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 501 | iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
502 | { | 502 | { |
503 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 503 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
504 | struct iscsi_r2t_info *r2t; | 504 | struct iscsi_r2t_info *r2t; |
505 | 505 | ||
506 | /* nothing to do for mgmt ctasks */ | ||
507 | if (!ctask->sc) | ||
508 | return; | ||
509 | |||
506 | /* flush ctask's r2t queues */ | 510 | /* flush ctask's r2t queues */ |
507 | while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { | 511 | while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { |
508 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, | 512 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, |
@@ -521,7 +525,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
521 | /** | 525 | /** |
522 | * iscsi_data_rsp - SCSI Data-In Response processing | 526 | * iscsi_data_rsp - SCSI Data-In Response processing |
523 | * @conn: iscsi connection | 527 | * @conn: iscsi connection |
524 | * @ctask: scsi command task | 528 | * @ctask: scsi command ctask |
525 | **/ | 529 | **/ |
526 | static int | 530 | static int |
527 | iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 531 | iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
@@ -578,7 +582,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
578 | /** | 582 | /** |
579 | * iscsi_solicit_data_init - initialize first Data-Out | 583 | * iscsi_solicit_data_init - initialize first Data-Out |
580 | * @conn: iscsi connection | 584 | * @conn: iscsi connection |
581 | * @ctask: scsi command task | 585 | * @ctask: scsi command ctask |
582 | * @r2t: R2T info | 586 | * @r2t: R2T info |
583 | * | 587 | * |
584 | * Notes: | 588 | * Notes: |
@@ -620,7 +624,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
620 | /** | 624 | /** |
621 | * iscsi_r2t_rsp - iSCSI R2T Response processing | 625 | * iscsi_r2t_rsp - iSCSI R2T Response processing |
622 | * @conn: iscsi connection | 626 | * @conn: iscsi connection |
623 | * @ctask: scsi command task | 627 | * @ctask: scsi command ctask |
624 | **/ | 628 | **/ |
625 | static int | 629 | static int |
626 | iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 630 | iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
@@ -646,7 +650,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
646 | return ISCSI_ERR_R2TSN; | 650 | return ISCSI_ERR_R2TSN; |
647 | } | 651 | } |
648 | 652 | ||
649 | /* fill-in new R2T associated with the task */ | 653 | /* fill-in new R2T associated with the ctask */ |
650 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); | 654 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); |
651 | 655 | ||
652 | if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { | 656 | if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { |
@@ -769,6 +773,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
769 | ctask = iscsi_itt_to_ctask(conn, hdr->itt); | 773 | ctask = iscsi_itt_to_ctask(conn, hdr->itt); |
770 | if (!ctask) | 774 | if (!ctask) |
771 | return ISCSI_ERR_BAD_ITT; | 775 | return ISCSI_ERR_BAD_ITT; |
776 | if (!ctask->sc) | ||
777 | return ISCSI_ERR_NO_SCSI_CMD; | ||
772 | 778 | ||
773 | spin_lock(&conn->session->lock); | 779 | spin_lock(&conn->session->lock); |
774 | rc = iscsi_data_rsp(conn, ctask); | 780 | rc = iscsi_data_rsp(conn, ctask); |
@@ -815,6 +821,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
815 | ctask = iscsi_itt_to_ctask(conn, hdr->itt); | 821 | ctask = iscsi_itt_to_ctask(conn, hdr->itt); |
816 | if (!ctask) | 822 | if (!ctask) |
817 | return ISCSI_ERR_BAD_ITT; | 823 | return ISCSI_ERR_BAD_ITT; |
824 | if (!ctask->sc) | ||
825 | return ISCSI_ERR_NO_SCSI_CMD; | ||
818 | 826 | ||
819 | if (ahslen) | 827 | if (ahslen) |
820 | rc = ISCSI_ERR_AHSLEN; | 828 | rc = ISCSI_ERR_AHSLEN; |
@@ -1194,7 +1202,7 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen) | |||
1194 | 1202 | ||
1195 | /* If header digest is enabled, compute the CRC and | 1203 | /* If header digest is enabled, compute the CRC and |
1196 | * place the digest into the same buffer. We make | 1204 | * place the digest into the same buffer. We make |
1197 | * sure that both iscsi_tcp_ctask and mtask have | 1205 | * sure that both iscsi_tcp_cmd_task and mctask have |
1198 | * sufficient room. | 1206 | * sufficient room. |
1199 | */ | 1207 | */ |
1200 | if (conn->hdrdgst_en) { | 1208 | if (conn->hdrdgst_en) { |
@@ -1269,7 +1277,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data, | |||
1269 | /** | 1277 | /** |
1270 | * iscsi_solicit_data_cont - initialize next Data-Out | 1278 | * iscsi_solicit_data_cont - initialize next Data-Out |
1271 | * @conn: iscsi connection | 1279 | * @conn: iscsi connection |
1272 | * @ctask: scsi command task | 1280 | * @ctask: scsi command ctask |
1273 | * @r2t: R2T info | 1281 | * @r2t: R2T info |
1274 | * @left: bytes left to transfer | 1282 | * @left: bytes left to transfer |
1275 | * | 1283 | * |
@@ -1316,19 +1324,37 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1316 | } | 1324 | } |
1317 | 1325 | ||
1318 | /** | 1326 | /** |
1319 | * iscsi_tcp_ctask - Initialize iSCSI SCSI_READ or SCSI_WRITE commands | 1327 | * iscsi_tcp_task - Initialize iSCSI SCSI_READ or SCSI_WRITE commands |
1320 | * @conn: iscsi connection | 1328 | * @conn: iscsi connection |
1321 | * @ctask: scsi command task | 1329 | * @ctask: scsi command ctask |
1322 | * @sc: scsi command | 1330 | * @sc: scsi command |
1323 | **/ | 1331 | **/ |
1324 | static int | 1332 | static int |
1325 | iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask) | 1333 | iscsi_tcp_task_init(struct iscsi_cmd_task *ctask) |
1326 | { | 1334 | { |
1327 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1335 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1328 | struct iscsi_conn *conn = ctask->conn; | 1336 | struct iscsi_conn *conn = ctask->conn; |
1329 | struct scsi_cmnd *sc = ctask->sc; | 1337 | struct scsi_cmnd *sc = ctask->sc; |
1330 | int err; | 1338 | int err; |
1331 | 1339 | ||
1340 | if (!sc) { | ||
1341 | /* | ||
1342 | * mgmt ctasks do not have a scatterlist since they come | ||
1343 | * in from the iscsi interface. | ||
1344 | */ | ||
1345 | debug_scsi("mctask deq [cid %d itt 0x%x]\n", conn->id, | ||
1346 | ctask->itt); | ||
1347 | |||
1348 | /* Prepare PDU, optionally w/ immediate data */ | ||
1349 | iscsi_tcp_send_hdr_prep(conn, ctask->hdr, sizeof(*ctask->hdr)); | ||
1350 | |||
1351 | /* If we have immediate data, attach a payload */ | ||
1352 | if (ctask->data_count) | ||
1353 | iscsi_tcp_send_linear_data_prepare(conn, ctask->data, | ||
1354 | ctask->data_count); | ||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1332 | BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); | 1358 | BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); |
1333 | tcp_ctask->sent = 0; | 1359 | tcp_ctask->sent = 0; |
1334 | tcp_ctask->exp_datasn = 0; | 1360 | tcp_ctask->exp_datasn = 0; |
@@ -1353,52 +1379,21 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask) | |||
1353 | return 0; | 1379 | return 0; |
1354 | } | 1380 | } |
1355 | 1381 | ||
1356 | /** | ||
1357 | * iscsi_tcp_mtask_xmit - xmit management(immediate) task | ||
1358 | * @conn: iscsi connection | ||
1359 | * @mtask: task management task | ||
1360 | * | ||
1361 | * Notes: | ||
1362 | * The function can return -EAGAIN in which case caller must | ||
1363 | * call it again later, or recover. '0' return code means successful | ||
1364 | * xmit. | ||
1365 | **/ | ||
1366 | static int | ||
1367 | iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | ||
1368 | { | ||
1369 | int rc; | ||
1370 | |||
1371 | /* Flush any pending data first. */ | ||
1372 | rc = iscsi_tcp_flush(conn); | ||
1373 | if (rc < 0) | ||
1374 | return rc; | ||
1375 | |||
1376 | if (mtask->hdr->itt == RESERVED_ITT) { | ||
1377 | struct iscsi_session *session = conn->session; | ||
1378 | |||
1379 | spin_lock_bh(&session->lock); | ||
1380 | iscsi_free_mgmt_task(conn, mtask); | ||
1381 | spin_unlock_bh(&session->lock); | ||
1382 | } | ||
1383 | |||
1384 | return 0; | ||
1385 | } | ||
1386 | |||
1387 | /* | 1382 | /* |
1388 | * iscsi_tcp_ctask_xmit - xmit normal PDU task | 1383 | * iscsi_tcp_task_xmit - xmit normal PDU ctask |
1389 | * @conn: iscsi connection | 1384 | * @ctask: iscsi command ctask |
1390 | * @ctask: iscsi command task | ||
1391 | * | 1385 | * |
1392 | * We're expected to return 0 when everything was transmitted succesfully, | 1386 | * We're expected to return 0 when everything was transmitted succesfully, |
1393 | * -EAGAIN if there's still data in the queue, or != 0 for any other kind | 1387 | * -EAGAIN if there's still data in the queue, or != 0 for any other kind |
1394 | * of error. | 1388 | * of error. |
1395 | */ | 1389 | */ |
1396 | static int | 1390 | static int |
1397 | iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1391 | iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask) |
1398 | { | 1392 | { |
1393 | struct iscsi_conn *conn = ctask->conn; | ||
1399 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1394 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1400 | struct scsi_cmnd *sc = ctask->sc; | 1395 | struct scsi_cmnd *sc = ctask->sc; |
1401 | struct scsi_data_buffer *sdb = scsi_out(sc); | 1396 | struct scsi_data_buffer *sdb; |
1402 | int rc = 0; | 1397 | int rc = 0; |
1403 | 1398 | ||
1404 | flush: | 1399 | flush: |
@@ -1407,10 +1402,18 @@ flush: | |||
1407 | if (rc < 0) | 1402 | if (rc < 0) |
1408 | return rc; | 1403 | return rc; |
1409 | 1404 | ||
1405 | /* mgmt command */ | ||
1406 | if (!sc) { | ||
1407 | if (ctask->hdr->itt == RESERVED_ITT) | ||
1408 | iscsi_put_ctask(ctask); | ||
1409 | return 0; | ||
1410 | } | ||
1411 | |||
1410 | /* Are we done already? */ | 1412 | /* Are we done already? */ |
1411 | if (sc->sc_data_direction != DMA_TO_DEVICE) | 1413 | if (sc->sc_data_direction != DMA_TO_DEVICE) |
1412 | return 0; | 1414 | return 0; |
1413 | 1415 | ||
1416 | sdb = scsi_out(sc); | ||
1414 | if (ctask->unsol_count != 0) { | 1417 | if (ctask->unsol_count != 0) { |
1415 | struct iscsi_data *hdr = &tcp_ctask->unsol_dtask.hdr; | 1418 | struct iscsi_data *hdr = &tcp_ctask->unsol_dtask.hdr; |
1416 | 1419 | ||
@@ -1688,21 +1691,6 @@ free_socket: | |||
1688 | return err; | 1691 | return err; |
1689 | } | 1692 | } |
1690 | 1693 | ||
1691 | /* called with host lock */ | ||
1692 | static void | ||
1693 | iscsi_tcp_mtask_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | ||
1694 | { | ||
1695 | debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt); | ||
1696 | |||
1697 | /* Prepare PDU, optionally w/ immediate data */ | ||
1698 | iscsi_tcp_send_hdr_prep(conn, mtask->hdr, sizeof(*mtask->hdr)); | ||
1699 | |||
1700 | /* If we have immediate data, attach a payload */ | ||
1701 | if (mtask->data_count) | ||
1702 | iscsi_tcp_send_linear_data_prepare(conn, mtask->data, | ||
1703 | mtask->data_count); | ||
1704 | } | ||
1705 | |||
1706 | static int | 1694 | static int |
1707 | iscsi_r2tpool_alloc(struct iscsi_session *session) | 1695 | iscsi_r2tpool_alloc(struct iscsi_session *session) |
1708 | { | 1696 | { |
@@ -1710,7 +1698,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) | |||
1710 | int cmd_i; | 1698 | int cmd_i; |
1711 | 1699 | ||
1712 | /* | 1700 | /* |
1713 | * initialize per-task: R2T pool and xmit queue | 1701 | * initialize per-ctask: R2T pool and xmit queue |
1714 | */ | 1702 | */ |
1715 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | 1703 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
1716 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 1704 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; |
@@ -1880,13 +1868,12 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
1880 | 1868 | ||
1881 | cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max, | 1869 | cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max, |
1882 | sizeof(struct iscsi_tcp_cmd_task), | 1870 | sizeof(struct iscsi_tcp_cmd_task), |
1883 | sizeof(struct iscsi_tcp_mgmt_task), | ||
1884 | initial_cmdsn); | 1871 | initial_cmdsn); |
1885 | if (!cls_session) | 1872 | if (!cls_session) |
1886 | goto remove_host; | 1873 | goto remove_host; |
1887 | session = cls_session->dd_data; | 1874 | session = cls_session->dd_data; |
1888 | 1875 | ||
1889 | shost->can_queue = session->cmds_max; | 1876 | shost->can_queue = session->scsi_cmds_max; |
1890 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | 1877 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
1891 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 1878 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; |
1892 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1879 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
@@ -1895,13 +1882,6 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
1895 | ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE; | 1882 | ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE; |
1896 | } | 1883 | } |
1897 | 1884 | ||
1898 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { | ||
1899 | struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; | ||
1900 | struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; | ||
1901 | |||
1902 | mtask->hdr = (struct iscsi_hdr *) &tcp_mtask->hdr; | ||
1903 | } | ||
1904 | |||
1905 | if (iscsi_r2tpool_alloc(session)) | 1885 | if (iscsi_r2tpool_alloc(session)) |
1906 | goto remove_session; | 1886 | goto remove_session; |
1907 | return cls_session; | 1887 | return cls_session; |
@@ -1999,11 +1979,9 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
1999 | /* IO */ | 1979 | /* IO */ |
2000 | .send_pdu = iscsi_conn_send_pdu, | 1980 | .send_pdu = iscsi_conn_send_pdu, |
2001 | .get_stats = iscsi_conn_get_stats, | 1981 | .get_stats = iscsi_conn_get_stats, |
2002 | .init_cmd_task = iscsi_tcp_ctask_init, | 1982 | .init_task = iscsi_tcp_task_init, |
2003 | .init_mgmt_task = iscsi_tcp_mtask_init, | 1983 | .xmit_task = iscsi_tcp_task_xmit, |
2004 | .xmit_cmd_task = iscsi_tcp_ctask_xmit, | 1984 | .cleanup_task = iscsi_tcp_cleanup_task, |
2005 | .xmit_mgmt_task = iscsi_tcp_mtask_xmit, | ||
2006 | .cleanup_cmd_task = iscsi_tcp_cleanup_ctask, | ||
2007 | /* recovery */ | 1985 | /* recovery */ |
2008 | .session_recovery_timedout = iscsi_session_recovery_timedout, | 1986 | .session_recovery_timedout = iscsi_session_recovery_timedout, |
2009 | }; | 1987 | }; |