diff options
author | James Bottomley <jejb@sparkweed.localdomain> | 2006-09-23 16:33:43 -0400 |
---|---|---|
committer | James Bottomley <jejb@sparkweed.localdomain> | 2006-09-23 16:33:43 -0400 |
commit | c9802cd9574a80444e689c7525627b40d7dc3a06 (patch) | |
tree | 5954e2ac7e97023b51d36127963a1e9262fbcfe0 /drivers/scsi/iscsi_tcp.c | |
parent | 3eeab61aa3ddd3c0bedb7449ada1599de22fdb5a (diff) | |
parent | 2d2f8d59b14bec6c745e219a350ac51d9e00673f (diff) |
Merge mulgrave-w:git/scsi-misc-2.6
Conflicts:
drivers/scsi/iscsi_tcp.c
drivers/scsi/iscsi_tcp.h
Pretty horrible merge between crypto hash consolidation
and crypto_digest_...->crypto_hash_... conversion
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 811 |
1 files changed, 312 insertions, 499 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 66a1ae1d6982..0a9dbc59663f 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -26,7 +26,6 @@ | |||
26 | * Zhenyu Wang | 26 | * Zhenyu Wang |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/err.h> | ||
30 | #include <linux/types.h> | 29 | #include <linux/types.h> |
31 | #include <linux/list.h> | 30 | #include <linux/list.h> |
32 | #include <linux/inet.h> | 31 | #include <linux/inet.h> |
@@ -108,12 +107,9 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf, | |||
108 | u8* crc) | 107 | u8* crc) |
109 | { | 108 | { |
110 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 109 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
111 | struct hash_desc desc; | ||
112 | 110 | ||
113 | desc.tfm = tcp_conn->tx_tfm; | 111 | crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc); |
114 | desc.flags = 0; | 112 | buf->sg.length = tcp_conn->hdr_size; |
115 | crypto_hash_digest(&desc, &buf->sg, buf->sg.length, crc); | ||
116 | buf->sg.length += sizeof(uint32_t); | ||
117 | } | 113 | } |
118 | 114 | ||
119 | static inline int | 115 | static inline int |
@@ -285,7 +281,6 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
285 | { | 281 | { |
286 | struct iscsi_data *hdr; | 282 | struct iscsi_data *hdr; |
287 | struct scsi_cmnd *sc = ctask->sc; | 283 | struct scsi_cmnd *sc = ctask->sc; |
288 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | ||
289 | 284 | ||
290 | hdr = &r2t->dtask.hdr; | 285 | hdr = &r2t->dtask.hdr; |
291 | memset(hdr, 0, sizeof(struct iscsi_data)); | 286 | memset(hdr, 0, sizeof(struct iscsi_data)); |
@@ -340,10 +335,12 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
340 | sg_count += sg->length; | 335 | sg_count += sg->length; |
341 | } | 336 | } |
342 | BUG_ON(r2t->sg == NULL); | 337 | BUG_ON(r2t->sg == NULL); |
343 | } else | 338 | } else { |
344 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, | 339 | iscsi_buf_init_iov(&r2t->sendbuf, |
345 | (char*)sc->request_buffer + r2t->data_offset, | 340 | (char*)sc->request_buffer + r2t->data_offset, |
346 | r2t->data_count); | 341 | r2t->data_count); |
342 | r2t->sg = NULL; | ||
343 | } | ||
347 | } | 344 | } |
348 | 345 | ||
349 | /** | 346 | /** |
@@ -362,8 +359,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
362 | int r2tsn = be32_to_cpu(rhdr->r2tsn); | 359 | int r2tsn = be32_to_cpu(rhdr->r2tsn); |
363 | int rc; | 360 | int rc; |
364 | 361 | ||
365 | if (tcp_conn->in.datalen) | 362 | if (tcp_conn->in.datalen) { |
363 | printk(KERN_ERR "iscsi_tcp: invalid R2t with datalen %d\n", | ||
364 | tcp_conn->in.datalen); | ||
366 | return ISCSI_ERR_DATALEN; | 365 | return ISCSI_ERR_DATALEN; |
366 | } | ||
367 | 367 | ||
368 | if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn) | 368 | if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn) |
369 | return ISCSI_ERR_R2TSN; | 369 | return ISCSI_ERR_R2TSN; |
@@ -389,15 +389,23 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
389 | 389 | ||
390 | r2t->exp_statsn = rhdr->statsn; | 390 | r2t->exp_statsn = rhdr->statsn; |
391 | r2t->data_length = be32_to_cpu(rhdr->data_length); | 391 | r2t->data_length = be32_to_cpu(rhdr->data_length); |
392 | if (r2t->data_length == 0 || | 392 | if (r2t->data_length == 0) { |
393 | r2t->data_length > session->max_burst) { | 393 | printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n"); |
394 | spin_unlock(&session->lock); | 394 | spin_unlock(&session->lock); |
395 | return ISCSI_ERR_DATALEN; | 395 | return ISCSI_ERR_DATALEN; |
396 | } | 396 | } |
397 | 397 | ||
398 | if (r2t->data_length > session->max_burst) | ||
399 | debug_scsi("invalid R2T with data len %u and max burst %u." | ||
400 | "Attempting to execute request.\n", | ||
401 | r2t->data_length, session->max_burst); | ||
402 | |||
398 | r2t->data_offset = be32_to_cpu(rhdr->data_offset); | 403 | r2t->data_offset = be32_to_cpu(rhdr->data_offset); |
399 | if (r2t->data_offset + r2t->data_length > ctask->total_length) { | 404 | if (r2t->data_offset + r2t->data_length > ctask->total_length) { |
400 | spin_unlock(&session->lock); | 405 | spin_unlock(&session->lock); |
406 | printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at " | ||
407 | "offset %u and total length %d\n", r2t->data_length, | ||
408 | r2t->data_offset, ctask->total_length); | ||
401 | return ISCSI_ERR_DATALEN; | 409 | return ISCSI_ERR_DATALEN; |
402 | } | 410 | } |
403 | 411 | ||
@@ -456,14 +464,12 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) | |||
456 | } | 464 | } |
457 | 465 | ||
458 | if (conn->hdrdgst_en) { | 466 | if (conn->hdrdgst_en) { |
459 | struct hash_desc desc; | ||
460 | struct scatterlist sg; | 467 | struct scatterlist sg; |
461 | 468 | ||
462 | sg_init_one(&sg, (u8 *)hdr, | 469 | sg_init_one(&sg, (u8 *)hdr, |
463 | sizeof(struct iscsi_hdr) + ahslen); | 470 | sizeof(struct iscsi_hdr) + ahslen); |
464 | desc.tfm = tcp_conn->rx_tfm; | 471 | crypto_hash_digest(&tcp_conn->rx_hash, &sg, sg.length, |
465 | desc.flags = 0; | 472 | (u8 *)&cdgst); |
466 | crypto_hash_digest(&desc, &sg, sg.length, (u8 *)&cdgst); | ||
467 | rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + | 473 | rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + |
468 | ahslen); | 474 | ahslen); |
469 | if (cdgst != rdgst) { | 475 | if (cdgst != rdgst) { |
@@ -499,7 +505,6 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) | |||
499 | goto copy_hdr; | 505 | goto copy_hdr; |
500 | 506 | ||
501 | spin_lock(&session->lock); | 507 | spin_lock(&session->lock); |
502 | iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask); | ||
503 | rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); | 508 | rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); |
504 | spin_unlock(&session->lock); | 509 | spin_unlock(&session->lock); |
505 | break; | 510 | break; |
@@ -644,10 +649,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, | |||
644 | * byte counters. | 649 | * byte counters. |
645 | **/ | 650 | **/ |
646 | static inline int | 651 | static inline int |
647 | iscsi_tcp_copy(struct iscsi_conn *conn) | 652 | iscsi_tcp_copy(struct iscsi_conn *conn, int buf_size) |
648 | { | 653 | { |
649 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 654 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
650 | int buf_size = tcp_conn->in.datalen; | ||
651 | int buf_left = buf_size - tcp_conn->data_copied; | 655 | int buf_left = buf_size - tcp_conn->data_copied; |
652 | int size = min(tcp_conn->in.copy, buf_left); | 656 | int size = min(tcp_conn->in.copy, buf_left); |
653 | int rc; | 657 | int rc; |
@@ -672,15 +676,15 @@ iscsi_tcp_copy(struct iscsi_conn *conn) | |||
672 | } | 676 | } |
673 | 677 | ||
674 | static inline void | 678 | static inline void |
675 | partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn, | 679 | partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg, |
676 | struct scatterlist *sg, int offset, int length) | 680 | int offset, int length) |
677 | { | 681 | { |
678 | struct scatterlist temp; | 682 | struct scatterlist temp; |
679 | 683 | ||
680 | memcpy(&temp, sg, sizeof(struct scatterlist)); | 684 | memcpy(&temp, sg, sizeof(struct scatterlist)); |
681 | temp.offset = offset; | 685 | temp.offset = offset; |
682 | temp.length = length; | 686 | temp.length = length; |
683 | crypto_hash_update(&tcp_conn->data_rx_hash, &temp, length); | 687 | crypto_hash_update(desc, &temp, length); |
684 | } | 688 | } |
685 | 689 | ||
686 | static void | 690 | static void |
@@ -689,7 +693,7 @@ iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len) | |||
689 | struct scatterlist tmp; | 693 | struct scatterlist tmp; |
690 | 694 | ||
691 | sg_init_one(&tmp, buf, len); | 695 | sg_init_one(&tmp, buf, len); |
692 | crypto_hash_update(&tcp_conn->data_rx_hash, &tmp, len); | 696 | crypto_hash_update(&tcp_conn->rx_hash, &tmp, len); |
693 | } | 697 | } |
694 | 698 | ||
695 | static int iscsi_scsi_data_in(struct iscsi_conn *conn) | 699 | static int iscsi_scsi_data_in(struct iscsi_conn *conn) |
@@ -744,10 +748,11 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) | |||
744 | if (conn->datadgst_en) { | 748 | if (conn->datadgst_en) { |
745 | if (!offset) | 749 | if (!offset) |
746 | crypto_hash_update( | 750 | crypto_hash_update( |
747 | &tcp_conn->data_rx_hash, | 751 | &tcp_conn->rx_hash, |
748 | &sg[i], sg[i].length); | 752 | &sg[i], 1); |
749 | else | 753 | else |
750 | partial_sg_digest_update(tcp_conn, | 754 | partial_sg_digest_update( |
755 | &tcp_conn->rx_hash, | ||
751 | &sg[i], | 756 | &sg[i], |
752 | sg[i].offset + offset, | 757 | sg[i].offset + offset, |
753 | sg[i].length - offset); | 758 | sg[i].length - offset); |
@@ -761,8 +766,10 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) | |||
761 | /* | 766 | /* |
762 | * data-in is complete, but buffer not... | 767 | * data-in is complete, but buffer not... |
763 | */ | 768 | */ |
764 | partial_sg_digest_update(tcp_conn, &sg[i], | 769 | partial_sg_digest_update(&tcp_conn->rx_hash, |
765 | sg[i].offset, sg[i].length-rc); | 770 | &sg[i], |
771 | sg[i].offset, | ||
772 | sg[i].length-rc); | ||
766 | rc = 0; | 773 | rc = 0; |
767 | break; | 774 | break; |
768 | } | 775 | } |
@@ -779,7 +786,6 @@ done: | |||
779 | (long)sc, sc->result, ctask->itt, | 786 | (long)sc, sc->result, ctask->itt, |
780 | tcp_conn->in.hdr->flags); | 787 | tcp_conn->in.hdr->flags); |
781 | spin_lock(&conn->session->lock); | 788 | spin_lock(&conn->session->lock); |
782 | iscsi_tcp_cleanup_ctask(conn, ctask); | ||
783 | __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); | 789 | __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); |
784 | spin_unlock(&conn->session->lock); | 790 | spin_unlock(&conn->session->lock); |
785 | } | 791 | } |
@@ -799,9 +805,6 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
799 | rc = iscsi_scsi_data_in(conn); | 805 | rc = iscsi_scsi_data_in(conn); |
800 | break; | 806 | break; |
801 | case ISCSI_OP_SCSI_CMD_RSP: | 807 | case ISCSI_OP_SCSI_CMD_RSP: |
802 | spin_lock(&conn->session->lock); | ||
803 | iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask); | ||
804 | spin_unlock(&conn->session->lock); | ||
805 | case ISCSI_OP_TEXT_RSP: | 808 | case ISCSI_OP_TEXT_RSP: |
806 | case ISCSI_OP_LOGIN_RSP: | 809 | case ISCSI_OP_LOGIN_RSP: |
807 | case ISCSI_OP_ASYNC_EVENT: | 810 | case ISCSI_OP_ASYNC_EVENT: |
@@ -810,7 +813,7 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
810 | * Collect data segment to the connection's data | 813 | * Collect data segment to the connection's data |
811 | * placeholder | 814 | * placeholder |
812 | */ | 815 | */ |
813 | if (iscsi_tcp_copy(conn)) { | 816 | if (iscsi_tcp_copy(conn, tcp_conn->in.datalen)) { |
814 | rc = -EAGAIN; | 817 | rc = -EAGAIN; |
815 | goto exit; | 818 | goto exit; |
816 | } | 819 | } |
@@ -883,9 +886,8 @@ more: | |||
883 | */ | 886 | */ |
884 | rc = iscsi_tcp_hdr_recv(conn); | 887 | rc = iscsi_tcp_hdr_recv(conn); |
885 | if (!rc && tcp_conn->in.datalen) { | 888 | if (!rc && tcp_conn->in.datalen) { |
886 | if (conn->datadgst_en) { | 889 | if (conn->datadgst_en) |
887 | crypto_hash_init(&tcp_conn->data_rx_hash); | 890 | crypto_hash_init(&tcp_conn->rx_hash); |
888 | } | ||
889 | tcp_conn->in_progress = IN_PROGRESS_DATA_RECV; | 891 | tcp_conn->in_progress = IN_PROGRESS_DATA_RECV; |
890 | } else if (rc) { | 892 | } else if (rc) { |
891 | iscsi_conn_failure(conn, rc); | 893 | iscsi_conn_failure(conn, rc); |
@@ -898,10 +900,15 @@ more: | |||
898 | 900 | ||
899 | debug_tcp("extra data_recv offset %d copy %d\n", | 901 | debug_tcp("extra data_recv offset %d copy %d\n", |
900 | tcp_conn->in.offset, tcp_conn->in.copy); | 902 | tcp_conn->in.offset, tcp_conn->in.copy); |
901 | skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, | 903 | rc = iscsi_tcp_copy(conn, sizeof(uint32_t)); |
902 | &recv_digest, 4); | 904 | if (rc) { |
903 | tcp_conn->in.offset += 4; | 905 | if (rc == -EAGAIN) |
904 | tcp_conn->in.copy -= 4; | 906 | goto again; |
907 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | memcpy(&recv_digest, conn->data, sizeof(uint32_t)); | ||
905 | if (recv_digest != tcp_conn->in.datadgst) { | 912 | if (recv_digest != tcp_conn->in.datadgst) { |
906 | debug_tcp("iscsi_tcp: data digest error!" | 913 | debug_tcp("iscsi_tcp: data digest error!" |
907 | "0x%x != 0x%x\n", recv_digest, | 914 | "0x%x != 0x%x\n", recv_digest, |
@@ -937,13 +944,14 @@ more: | |||
937 | tcp_conn->in.padding); | 944 | tcp_conn->in.padding); |
938 | memset(pad, 0, tcp_conn->in.padding); | 945 | memset(pad, 0, tcp_conn->in.padding); |
939 | sg_init_one(&sg, pad, tcp_conn->in.padding); | 946 | sg_init_one(&sg, pad, tcp_conn->in.padding); |
940 | crypto_hash_update(&tcp_conn->data_rx_hash, | 947 | crypto_hash_update(&tcp_conn->rx_hash, |
941 | &sg, sg.length); | 948 | &sg, sg.length); |
942 | } | 949 | } |
943 | crypto_hash_final(&tcp_conn->data_rx_hash, | 950 | crypto_hash_final(&tcp_conn->rx_hash, |
944 | (u8 *)&tcp_conn->in.datadgst); | 951 | (u8 *) &tcp_conn->in.datadgst); |
945 | debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); | 952 | debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); |
946 | tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; | 953 | tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; |
954 | tcp_conn->data_copied = 0; | ||
947 | } else | 955 | } else |
948 | tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; | 956 | tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; |
949 | } | 957 | } |
@@ -1183,36 +1191,12 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, | |||
1183 | 1191 | ||
1184 | static inline void | 1192 | static inline void |
1185 | iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, | 1193 | iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, |
1186 | struct iscsi_cmd_task *ctask) | 1194 | struct iscsi_tcp_cmd_task *tcp_ctask) |
1187 | { | 1195 | { |
1188 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1196 | crypto_hash_init(&tcp_conn->tx_hash); |
1189 | |||
1190 | crypto_hash_init(&tcp_conn->data_tx_hash); | ||
1191 | tcp_ctask->digest_count = 4; | 1197 | tcp_ctask->digest_count = 4; |
1192 | } | 1198 | } |
1193 | 1199 | ||
1194 | static int | ||
1195 | iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | ||
1196 | struct iscsi_buf *buf, uint32_t *digest, int final) | ||
1197 | { | ||
1198 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | ||
1199 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
1200 | int rc = 0; | ||
1201 | int sent = 0; | ||
1202 | |||
1203 | if (final) | ||
1204 | crypto_hash_final(&tcp_conn->data_tx_hash, (u8 *)digest); | ||
1205 | |||
1206 | iscsi_buf_init_iov(buf, (char*)digest, 4); | ||
1207 | rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); | ||
1208 | if (rc) { | ||
1209 | tcp_ctask->datadigest = *digest; | ||
1210 | tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; | ||
1211 | } else | ||
1212 | tcp_ctask->digest_count = 4; | ||
1213 | return rc; | ||
1214 | } | ||
1215 | |||
1216 | /** | 1200 | /** |
1217 | * iscsi_solicit_data_cont - initialize next Data-Out | 1201 | * iscsi_solicit_data_cont - initialize next Data-Out |
1218 | * @conn: iscsi connection | 1202 | * @conn: iscsi connection |
@@ -1230,7 +1214,6 @@ static void | |||
1230 | iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | 1214 | iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, |
1231 | struct iscsi_r2t_info *r2t, int left) | 1215 | struct iscsi_r2t_info *r2t, int left) |
1232 | { | 1216 | { |
1233 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | ||
1234 | struct iscsi_data *hdr; | 1217 | struct iscsi_data *hdr; |
1235 | struct scsi_cmnd *sc = ctask->sc; | 1218 | struct scsi_cmnd *sc = ctask->sc; |
1236 | int new_offset; | 1219 | int new_offset; |
@@ -1259,27 +1242,30 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1259 | iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, | 1242 | iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, |
1260 | sizeof(struct iscsi_hdr)); | 1243 | sizeof(struct iscsi_hdr)); |
1261 | 1244 | ||
1262 | if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) { | 1245 | if (iscsi_buf_left(&r2t->sendbuf)) |
1263 | BUG_ON(tcp_ctask->bad_sg == r2t->sg); | 1246 | return; |
1247 | |||
1248 | if (sc->use_sg) { | ||
1264 | iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); | 1249 | iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); |
1265 | r2t->sg += 1; | 1250 | r2t->sg += 1; |
1266 | } else | 1251 | } else { |
1267 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, | 1252 | iscsi_buf_init_iov(&r2t->sendbuf, |
1268 | (char*)sc->request_buffer + new_offset, | 1253 | (char*)sc->request_buffer + new_offset, |
1269 | r2t->data_count); | 1254 | r2t->data_count); |
1255 | r2t->sg = NULL; | ||
1256 | } | ||
1270 | } | 1257 | } |
1271 | 1258 | ||
1272 | static void | 1259 | static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask, |
1273 | iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1260 | unsigned long len) |
1274 | { | 1261 | { |
1275 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1262 | tcp_ctask->pad_count = len & (ISCSI_PAD_LEN - 1); |
1276 | struct iscsi_data_task *dtask; | 1263 | if (!tcp_ctask->pad_count) |
1264 | return; | ||
1277 | 1265 | ||
1278 | dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask; | 1266 | tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count; |
1279 | iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr, | 1267 | debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count); |
1280 | tcp_ctask->r2t_data_count); | 1268 | tcp_ctask->xmstate |= XMSTATE_W_PAD; |
1281 | iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr, | ||
1282 | sizeof(struct iscsi_hdr)); | ||
1283 | } | 1269 | } |
1284 | 1270 | ||
1285 | /** | 1271 | /** |
@@ -1307,38 +1293,20 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) | |||
1307 | if (sc->use_sg) { | 1293 | if (sc->use_sg) { |
1308 | struct scatterlist *sg = sc->request_buffer; | 1294 | struct scatterlist *sg = sc->request_buffer; |
1309 | 1295 | ||
1310 | iscsi_buf_init_sg(&tcp_ctask->sendbuf, | 1296 | iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg); |
1311 | &sg[tcp_ctask->sg_count++]); | 1297 | tcp_ctask->sg = sg + 1; |
1312 | tcp_ctask->sg = sg; | ||
1313 | tcp_ctask->bad_sg = sg + sc->use_sg; | 1298 | tcp_ctask->bad_sg = sg + sc->use_sg; |
1314 | } else | 1299 | } else { |
1315 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, | 1300 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, |
1316 | sc->request_buffer, | 1301 | sc->request_buffer, |
1317 | sc->request_bufflen); | 1302 | sc->request_bufflen); |
1318 | 1303 | tcp_ctask->sg = NULL; | |
1319 | if (ctask->imm_count) | 1304 | tcp_ctask->bad_sg = NULL; |
1320 | tcp_ctask->xmstate |= XMSTATE_IMM_DATA; | ||
1321 | |||
1322 | tcp_ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1); | ||
1323 | if (tcp_ctask->pad_count) { | ||
1324 | tcp_ctask->pad_count = ISCSI_PAD_LEN - | ||
1325 | tcp_ctask->pad_count; | ||
1326 | debug_scsi("write padding %d bytes\n", | ||
1327 | tcp_ctask->pad_count); | ||
1328 | tcp_ctask->xmstate |= XMSTATE_W_PAD; | ||
1329 | } | 1305 | } |
1330 | 1306 | debug_scsi("cmd [itt 0x%x total %d imm_data %d " | |
1331 | if (ctask->unsol_count) | 1307 | "unsol count %d, unsol offset %d]\n", |
1332 | tcp_ctask->xmstate |= XMSTATE_UNS_HDR | | ||
1333 | XMSTATE_UNS_INIT; | ||
1334 | tcp_ctask->r2t_data_count = ctask->total_length - | ||
1335 | ctask->imm_count - | ||
1336 | ctask->unsol_count; | ||
1337 | |||
1338 | debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d " | ||
1339 | "r2t_data %d]\n", | ||
1340 | ctask->itt, ctask->total_length, ctask->imm_count, | 1308 | ctask->itt, ctask->total_length, ctask->imm_count, |
1341 | ctask->unsol_count, tcp_ctask->r2t_data_count); | 1309 | ctask->unsol_count, ctask->unsol_offset); |
1342 | } else | 1310 | } else |
1343 | tcp_ctask->xmstate = XMSTATE_R_HDR; | 1311 | tcp_ctask->xmstate = XMSTATE_R_HDR; |
1344 | 1312 | ||
@@ -1420,8 +1388,8 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | |||
1420 | } | 1388 | } |
1421 | 1389 | ||
1422 | static inline int | 1390 | static inline int |
1423 | handle_xmstate_r_hdr(struct iscsi_conn *conn, | 1391 | iscsi_send_read_hdr(struct iscsi_conn *conn, |
1424 | struct iscsi_tcp_cmd_task *tcp_ctask) | 1392 | struct iscsi_tcp_cmd_task *tcp_ctask) |
1425 | { | 1393 | { |
1426 | int rc; | 1394 | int rc; |
1427 | 1395 | ||
@@ -1439,7 +1407,7 @@ handle_xmstate_r_hdr(struct iscsi_conn *conn, | |||
1439 | } | 1407 | } |
1440 | 1408 | ||
1441 | static inline int | 1409 | static inline int |
1442 | handle_xmstate_w_hdr(struct iscsi_conn *conn, | 1410 | iscsi_send_write_hdr(struct iscsi_conn *conn, |
1443 | struct iscsi_cmd_task *ctask) | 1411 | struct iscsi_cmd_task *ctask) |
1444 | { | 1412 | { |
1445 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1413 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
@@ -1450,86 +1418,126 @@ handle_xmstate_w_hdr(struct iscsi_conn *conn, | |||
1450 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, | 1418 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, |
1451 | (u8*)tcp_ctask->hdrext); | 1419 | (u8*)tcp_ctask->hdrext); |
1452 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); | 1420 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); |
1453 | if (rc) | 1421 | if (rc) { |
1454 | tcp_ctask->xmstate |= XMSTATE_W_HDR; | 1422 | tcp_ctask->xmstate |= XMSTATE_W_HDR; |
1455 | return rc; | 1423 | return rc; |
1424 | } | ||
1425 | |||
1426 | if (ctask->imm_count) { | ||
1427 | tcp_ctask->xmstate |= XMSTATE_IMM_DATA; | ||
1428 | iscsi_set_padding(tcp_ctask, ctask->imm_count); | ||
1429 | |||
1430 | if (ctask->conn->datadgst_en) { | ||
1431 | iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask); | ||
1432 | tcp_ctask->immdigest = 0; | ||
1433 | } | ||
1434 | } | ||
1435 | |||
1436 | if (ctask->unsol_count) | ||
1437 | tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; | ||
1438 | return 0; | ||
1456 | } | 1439 | } |
1457 | 1440 | ||
1458 | static inline int | 1441 | static int |
1459 | handle_xmstate_data_digest(struct iscsi_conn *conn, | 1442 | iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
1460 | struct iscsi_cmd_task *ctask) | ||
1461 | { | 1443 | { |
1462 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1444 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1463 | int rc; | 1445 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
1446 | int sent = 0, rc; | ||
1464 | 1447 | ||
1465 | tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST; | 1448 | if (tcp_ctask->xmstate & XMSTATE_W_PAD) { |
1466 | debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest); | 1449 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, |
1467 | rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, | 1450 | tcp_ctask->pad_count); |
1468 | &tcp_ctask->datadigest, 0); | 1451 | if (conn->datadgst_en) |
1452 | crypto_hash_update(&tcp_conn->tx_hash, | ||
1453 | &tcp_ctask->sendbuf.sg, | ||
1454 | tcp_ctask->sendbuf.sg.length); | ||
1455 | } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD)) | ||
1456 | return 0; | ||
1457 | |||
1458 | tcp_ctask->xmstate &= ~XMSTATE_W_PAD; | ||
1459 | tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD; | ||
1460 | debug_scsi("sending %d pad bytes for itt 0x%x\n", | ||
1461 | tcp_ctask->pad_count, ctask->itt); | ||
1462 | rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, | ||
1463 | &sent); | ||
1469 | if (rc) { | 1464 | if (rc) { |
1470 | tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; | 1465 | debug_scsi("padding send failed %d\n", rc); |
1471 | debug_tcp("resent data digest 0x%x fail!\n", | 1466 | tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD; |
1472 | tcp_ctask->datadigest); | ||
1473 | } | 1467 | } |
1474 | |||
1475 | return rc; | 1468 | return rc; |
1476 | } | 1469 | } |
1477 | 1470 | ||
1478 | static inline int | 1471 | static int |
1479 | handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1472 | iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, |
1473 | struct iscsi_buf *buf, uint32_t *digest) | ||
1480 | { | 1474 | { |
1481 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1475 | struct iscsi_tcp_cmd_task *tcp_ctask; |
1482 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1476 | struct iscsi_tcp_conn *tcp_conn; |
1483 | int rc; | 1477 | int rc, sent = 0; |
1484 | 1478 | ||
1485 | BUG_ON(!ctask->imm_count); | 1479 | if (!conn->datadgst_en) |
1486 | tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; | 1480 | return 0; |
1487 | 1481 | ||
1488 | if (conn->datadgst_en) { | 1482 | tcp_ctask = ctask->dd_data; |
1489 | iscsi_data_digest_init(tcp_conn, ctask); | 1483 | tcp_conn = conn->dd_data; |
1490 | tcp_ctask->immdigest = 0; | ||
1491 | } | ||
1492 | 1484 | ||
1493 | for (;;) { | 1485 | if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) { |
1494 | rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, | 1486 | crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest); |
1495 | &ctask->imm_count, &tcp_ctask->sent); | 1487 | iscsi_buf_init_iov(buf, (char*)digest, 4); |
1496 | if (rc) { | 1488 | } |
1497 | tcp_ctask->xmstate |= XMSTATE_IMM_DATA; | 1489 | tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST; |
1498 | if (conn->datadgst_en) { | ||
1499 | crypto_hash_final(&tcp_conn->data_tx_hash, | ||
1500 | (u8 *)&tcp_ctask->immdigest); | ||
1501 | debug_tcp("tx imm sendpage fail 0x%x\n", | ||
1502 | tcp_ctask->datadigest); | ||
1503 | } | ||
1504 | return rc; | ||
1505 | } | ||
1506 | if (conn->datadgst_en) | ||
1507 | crypto_hash_update(&tcp_conn->data_tx_hash, | ||
1508 | &tcp_ctask->sendbuf.sg, | ||
1509 | tcp_ctask->sendbuf.sg.length); | ||
1510 | 1490 | ||
1511 | if (!ctask->imm_count) | 1491 | rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); |
1512 | break; | 1492 | if (!rc) |
1513 | iscsi_buf_init_sg(&tcp_ctask->sendbuf, | 1493 | debug_scsi("sent digest 0x%x for itt 0x%x\n", *digest, |
1514 | &tcp_ctask->sg[tcp_ctask->sg_count++]); | 1494 | ctask->itt); |
1495 | else { | ||
1496 | debug_scsi("sending digest 0x%x failed for itt 0x%x!\n", | ||
1497 | *digest, ctask->itt); | ||
1498 | tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST; | ||
1515 | } | 1499 | } |
1500 | return rc; | ||
1501 | } | ||
1516 | 1502 | ||
1517 | if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { | 1503 | static int |
1518 | rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, | 1504 | iscsi_send_data(struct iscsi_cmd_task *ctask, struct iscsi_buf *sendbuf, |
1519 | &tcp_ctask->immdigest, 1); | 1505 | struct scatterlist **sg, int *sent, int *count, |
1520 | if (rc) { | 1506 | struct iscsi_buf *digestbuf, uint32_t *digest) |
1521 | debug_tcp("sending imm digest 0x%x fail!\n", | 1507 | { |
1522 | tcp_ctask->immdigest); | 1508 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1523 | return rc; | 1509 | struct iscsi_conn *conn = ctask->conn; |
1510 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
1511 | int rc, buf_sent, offset; | ||
1512 | |||
1513 | while (*count) { | ||
1514 | buf_sent = 0; | ||
1515 | offset = sendbuf->sent; | ||
1516 | |||
1517 | rc = iscsi_sendpage(conn, sendbuf, count, &buf_sent); | ||
1518 | *sent = *sent + buf_sent; | ||
1519 | if (buf_sent && conn->datadgst_en) | ||
1520 | partial_sg_digest_update(&tcp_conn->tx_hash, | ||
1521 | &sendbuf->sg, sendbuf->sg.offset + offset, | ||
1522 | buf_sent); | ||
1523 | if (!iscsi_buf_left(sendbuf) && *sg != tcp_ctask->bad_sg) { | ||
1524 | iscsi_buf_init_sg(sendbuf, *sg); | ||
1525 | *sg = *sg + 1; | ||
1524 | } | 1526 | } |
1525 | debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest); | 1527 | |
1528 | if (rc) | ||
1529 | return rc; | ||
1526 | } | 1530 | } |
1527 | 1531 | ||
1528 | return 0; | 1532 | rc = iscsi_send_padding(conn, ctask); |
1533 | if (rc) | ||
1534 | return rc; | ||
1535 | |||
1536 | return iscsi_send_digest(conn, ctask, digestbuf, digest); | ||
1529 | } | 1537 | } |
1530 | 1538 | ||
1531 | static inline int | 1539 | static int |
1532 | handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1540 | iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
1533 | { | 1541 | { |
1534 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1542 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1535 | struct iscsi_data_task *dtask; | 1543 | struct iscsi_data_task *dtask; |
@@ -1537,12 +1545,17 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1537 | 1545 | ||
1538 | tcp_ctask->xmstate |= XMSTATE_UNS_DATA; | 1546 | tcp_ctask->xmstate |= XMSTATE_UNS_DATA; |
1539 | if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { | 1547 | if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { |
1540 | iscsi_unsolicit_data_init(conn, ctask); | 1548 | dtask = &tcp_ctask->unsol_dtask; |
1541 | dtask = tcp_ctask->dtask; | 1549 | |
1550 | iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); | ||
1551 | iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr, | ||
1552 | sizeof(struct iscsi_hdr)); | ||
1542 | if (conn->hdrdgst_en) | 1553 | if (conn->hdrdgst_en) |
1543 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, | 1554 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, |
1544 | (u8*)dtask->hdrext); | 1555 | (u8*)dtask->hdrext); |
1556 | |||
1545 | tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; | 1557 | tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; |
1558 | iscsi_set_padding(tcp_ctask, ctask->data_count); | ||
1546 | } | 1559 | } |
1547 | 1560 | ||
1548 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); | 1561 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); |
@@ -1552,256 +1565,138 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1552 | return rc; | 1565 | return rc; |
1553 | } | 1566 | } |
1554 | 1567 | ||
1568 | if (conn->datadgst_en) { | ||
1569 | dtask = &tcp_ctask->unsol_dtask; | ||
1570 | iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask); | ||
1571 | dtask->digest = 0; | ||
1572 | } | ||
1573 | |||
1555 | debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n", | 1574 | debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n", |
1556 | ctask->itt, ctask->unsol_count, tcp_ctask->sent); | 1575 | ctask->itt, ctask->unsol_count, tcp_ctask->sent); |
1557 | return 0; | 1576 | return 0; |
1558 | } | 1577 | } |
1559 | 1578 | ||
1560 | static inline int | 1579 | static int |
1561 | handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1580 | iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
1562 | { | 1581 | { |
1563 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1582 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1564 | struct iscsi_data_task *dtask = tcp_ctask->dtask; | ||
1565 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
1566 | int rc; | 1583 | int rc; |
1567 | 1584 | ||
1568 | BUG_ON(!ctask->data_count); | 1585 | if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { |
1569 | tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; | 1586 | BUG_ON(!ctask->unsol_count); |
1570 | 1587 | tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; | |
1571 | if (conn->datadgst_en) { | 1588 | send_hdr: |
1572 | iscsi_data_digest_init(tcp_conn, ctask); | 1589 | rc = iscsi_send_unsol_hdr(conn, ctask); |
1573 | dtask->digest = 0; | 1590 | if (rc) |
1591 | return rc; | ||
1574 | } | 1592 | } |
1575 | 1593 | ||
1576 | for (;;) { | 1594 | if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { |
1595 | struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask; | ||
1577 | int start = tcp_ctask->sent; | 1596 | int start = tcp_ctask->sent; |
1578 | 1597 | ||
1579 | rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, | 1598 | rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, |
1580 | &ctask->data_count, &tcp_ctask->sent); | 1599 | &tcp_ctask->sent, &ctask->data_count, |
1581 | if (rc) { | 1600 | &dtask->digestbuf, &dtask->digest); |
1582 | ctask->unsol_count -= tcp_ctask->sent - start; | ||
1583 | tcp_ctask->xmstate |= XMSTATE_UNS_DATA; | ||
1584 | /* will continue with this ctask later.. */ | ||
1585 | if (conn->datadgst_en) { | ||
1586 | crypto_hash_final(&tcp_conn->data_tx_hash, | ||
1587 | (u8 *)&dtask->digest); | ||
1588 | debug_tcp("tx uns data fail 0x%x\n", | ||
1589 | dtask->digest); | ||
1590 | } | ||
1591 | return rc; | ||
1592 | } | ||
1593 | |||
1594 | BUG_ON(tcp_ctask->sent > ctask->total_length); | ||
1595 | ctask->unsol_count -= tcp_ctask->sent - start; | 1601 | ctask->unsol_count -= tcp_ctask->sent - start; |
1596 | 1602 | if (rc) | |
1603 | return rc; | ||
1604 | tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; | ||
1597 | /* | 1605 | /* |
1598 | * XXX:we may run here with un-initial sendbuf. | 1606 | * Done with the Data-Out. Next, check if we need |
1599 | * so pass it | 1607 | * to send another unsolicited Data-Out. |
1600 | */ | 1608 | */ |
1601 | if (conn->datadgst_en && tcp_ctask->sent - start > 0) | 1609 | if (ctask->unsol_count) { |
1602 | crypto_hash_update(&tcp_conn->data_tx_hash, | 1610 | debug_scsi("sending more uns\n"); |
1603 | &tcp_ctask->sendbuf.sg, | 1611 | tcp_ctask->xmstate |= XMSTATE_UNS_INIT; |
1604 | tcp_ctask->sendbuf.sg.length); | 1612 | goto send_hdr; |
1605 | |||
1606 | if (!ctask->data_count) | ||
1607 | break; | ||
1608 | iscsi_buf_init_sg(&tcp_ctask->sendbuf, | ||
1609 | &tcp_ctask->sg[tcp_ctask->sg_count++]); | ||
1610 | } | ||
1611 | BUG_ON(ctask->unsol_count < 0); | ||
1612 | |||
1613 | /* | ||
1614 | * Done with the Data-Out. Next, check if we need | ||
1615 | * to send another unsolicited Data-Out. | ||
1616 | */ | ||
1617 | if (ctask->unsol_count) { | ||
1618 | if (conn->datadgst_en) { | ||
1619 | rc = iscsi_digest_final_send(conn, ctask, | ||
1620 | &dtask->digestbuf, | ||
1621 | &dtask->digest, 1); | ||
1622 | if (rc) { | ||
1623 | debug_tcp("send uns digest 0x%x fail\n", | ||
1624 | dtask->digest); | ||
1625 | return rc; | ||
1626 | } | ||
1627 | debug_tcp("sending uns digest 0x%x, more uns\n", | ||
1628 | dtask->digest); | ||
1629 | } | 1613 | } |
1630 | tcp_ctask->xmstate |= XMSTATE_UNS_INIT; | ||
1631 | return 1; | ||
1632 | } | 1614 | } |
1633 | |||
1634 | if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { | ||
1635 | rc = iscsi_digest_final_send(conn, ctask, | ||
1636 | &dtask->digestbuf, | ||
1637 | &dtask->digest, 1); | ||
1638 | if (rc) { | ||
1639 | debug_tcp("send last uns digest 0x%x fail\n", | ||
1640 | dtask->digest); | ||
1641 | return rc; | ||
1642 | } | ||
1643 | debug_tcp("sending uns digest 0x%x\n",dtask->digest); | ||
1644 | } | ||
1645 | |||
1646 | return 0; | 1615 | return 0; |
1647 | } | 1616 | } |
1648 | 1617 | ||
1649 | static inline int | 1618 | static int iscsi_send_sol_pdu(struct iscsi_conn *conn, |
1650 | handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1619 | struct iscsi_cmd_task *ctask) |
1651 | { | 1620 | { |
1652 | struct iscsi_session *session = conn->session; | ||
1653 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
1654 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1621 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1655 | struct iscsi_r2t_info *r2t = tcp_ctask->r2t; | 1622 | struct iscsi_session *session = conn->session; |
1656 | struct iscsi_data_task *dtask = &r2t->dtask; | 1623 | struct iscsi_r2t_info *r2t; |
1624 | struct iscsi_data_task *dtask; | ||
1657 | int left, rc; | 1625 | int left, rc; |
1658 | 1626 | ||
1659 | tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; | 1627 | if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { |
1660 | tcp_ctask->dtask = dtask; | 1628 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; |
1661 | |||
1662 | if (conn->datadgst_en) { | ||
1663 | iscsi_data_digest_init(tcp_conn, ctask); | ||
1664 | dtask->digest = 0; | ||
1665 | } | ||
1666 | solicit_again: | ||
1667 | /* | ||
1668 | * send Data-Out within this R2T sequence. | ||
1669 | */ | ||
1670 | if (!r2t->data_count) | ||
1671 | goto data_out_done; | ||
1672 | |||
1673 | rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent); | ||
1674 | if (rc) { | ||
1675 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; | 1629 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; |
1676 | /* will continue with this ctask later.. */ | 1630 | if (!tcp_ctask->r2t) |
1677 | if (conn->datadgst_en) { | 1631 | __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, |
1678 | crypto_hash_final(&tcp_conn->data_tx_hash, | 1632 | sizeof(void*)); |
1679 | (u8 *)&dtask->digest); | 1633 | send_hdr: |
1680 | debug_tcp("r2t data send fail 0x%x\n", dtask->digest); | 1634 | r2t = tcp_ctask->r2t; |
1681 | } | 1635 | dtask = &r2t->dtask; |
1682 | return rc; | ||
1683 | } | ||
1684 | 1636 | ||
1685 | BUG_ON(r2t->data_count < 0); | 1637 | if (conn->hdrdgst_en) |
1686 | if (conn->datadgst_en) | 1638 | iscsi_hdr_digest(conn, &r2t->headbuf, |
1687 | crypto_hash_update(&tcp_conn->data_tx_hash, &r2t->sendbuf.sg, | 1639 | (u8*)dtask->hdrext); |
1688 | r2t->sendbuf.sg.length); | 1640 | rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); |
1689 | 1641 | if (rc) { | |
1690 | if (r2t->data_count) { | 1642 | tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; |
1691 | BUG_ON(ctask->sc->use_sg == 0); | 1643 | tcp_ctask->xmstate |= XMSTATE_SOL_HDR; |
1692 | if (!iscsi_buf_left(&r2t->sendbuf)) { | 1644 | return rc; |
1693 | BUG_ON(tcp_ctask->bad_sg == r2t->sg); | ||
1694 | iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); | ||
1695 | r2t->sg += 1; | ||
1696 | } | 1645 | } |
1697 | goto solicit_again; | ||
1698 | } | ||
1699 | 1646 | ||
1700 | data_out_done: | ||
1701 | /* | ||
1702 | * Done with this Data-Out. Next, check if we have | ||
1703 | * to send another Data-Out for this R2T. | ||
1704 | */ | ||
1705 | BUG_ON(r2t->data_length - r2t->sent < 0); | ||
1706 | left = r2t->data_length - r2t->sent; | ||
1707 | if (left) { | ||
1708 | if (conn->datadgst_en) { | 1647 | if (conn->datadgst_en) { |
1709 | rc = iscsi_digest_final_send(conn, ctask, | 1648 | iscsi_data_digest_init(conn->dd_data, tcp_ctask); |
1710 | &dtask->digestbuf, | 1649 | dtask->digest = 0; |
1711 | &dtask->digest, 1); | ||
1712 | if (rc) { | ||
1713 | debug_tcp("send r2t data digest 0x%x" | ||
1714 | "fail\n", dtask->digest); | ||
1715 | return rc; | ||
1716 | } | ||
1717 | debug_tcp("r2t data send digest 0x%x\n", | ||
1718 | dtask->digest); | ||
1719 | } | ||
1720 | iscsi_solicit_data_cont(conn, ctask, r2t, left); | ||
1721 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; | ||
1722 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; | ||
1723 | return 1; | ||
1724 | } | ||
1725 | |||
1726 | /* | ||
1727 | * Done with this R2T. Check if there are more | ||
1728 | * outstanding R2Ts ready to be processed. | ||
1729 | */ | ||
1730 | BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0); | ||
1731 | if (conn->datadgst_en) { | ||
1732 | rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, | ||
1733 | &dtask->digest, 1); | ||
1734 | if (rc) { | ||
1735 | debug_tcp("send last r2t data digest 0x%x" | ||
1736 | "fail\n", dtask->digest); | ||
1737 | return rc; | ||
1738 | } | 1650 | } |
1739 | debug_tcp("r2t done dout digest 0x%x\n", dtask->digest); | ||
1740 | } | ||
1741 | 1651 | ||
1742 | tcp_ctask->r2t_data_count -= r2t->data_length; | 1652 | iscsi_set_padding(tcp_ctask, r2t->data_count); |
1743 | tcp_ctask->r2t = NULL; | 1653 | debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n", |
1744 | spin_lock_bh(&session->lock); | 1654 | r2t->solicit_datasn - 1, ctask->itt, r2t->data_count, |
1745 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); | 1655 | r2t->sent); |
1746 | spin_unlock_bh(&session->lock); | ||
1747 | if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { | ||
1748 | tcp_ctask->r2t = r2t; | ||
1749 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; | ||
1750 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; | ||
1751 | return 1; | ||
1752 | } | 1656 | } |
1753 | 1657 | ||
1754 | return 0; | 1658 | if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { |
1755 | } | 1659 | r2t = tcp_ctask->r2t; |
1660 | dtask = &r2t->dtask; | ||
1756 | 1661 | ||
1757 | static inline int | 1662 | rc = iscsi_send_data(ctask, &r2t->sendbuf, &r2t->sg, |
1758 | handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1663 | &r2t->sent, &r2t->data_count, |
1759 | { | 1664 | &dtask->digestbuf, &dtask->digest); |
1760 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1665 | if (rc) |
1761 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1666 | return rc; |
1762 | struct iscsi_data_task *dtask = tcp_ctask->dtask; | 1667 | tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; |
1763 | int sent = 0, rc; | ||
1764 | 1668 | ||
1765 | tcp_ctask->xmstate &= ~XMSTATE_W_PAD; | 1669 | /* |
1766 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, | 1670 | * Done with this Data-Out. Next, check if we have |
1767 | tcp_ctask->pad_count); | 1671 | * to send another Data-Out for this R2T. |
1768 | rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, | 1672 | */ |
1769 | &sent); | 1673 | BUG_ON(r2t->data_length - r2t->sent < 0); |
1770 | if (rc) { | 1674 | left = r2t->data_length - r2t->sent; |
1771 | tcp_ctask->xmstate |= XMSTATE_W_PAD; | 1675 | if (left) { |
1772 | return rc; | 1676 | iscsi_solicit_data_cont(conn, ctask, r2t, left); |
1773 | } | 1677 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; |
1678 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; | ||
1679 | goto send_hdr; | ||
1680 | } | ||
1774 | 1681 | ||
1775 | if (conn->datadgst_en) { | 1682 | /* |
1776 | crypto_hash_update(&tcp_conn->data_tx_hash, | 1683 | * Done with this R2T. Check if there are more |
1777 | &tcp_ctask->sendbuf.sg, | 1684 | * outstanding R2Ts ready to be processed. |
1778 | tcp_ctask->sendbuf.sg.length); | 1685 | */ |
1779 | /* imm data? */ | 1686 | spin_lock_bh(&session->lock); |
1780 | if (!dtask) { | 1687 | tcp_ctask->r2t = NULL; |
1781 | rc = iscsi_digest_final_send(conn, ctask, | 1688 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, |
1782 | &tcp_ctask->immbuf, | 1689 | sizeof(void*)); |
1783 | &tcp_ctask->immdigest, 1); | 1690 | if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, |
1784 | if (rc) { | 1691 | sizeof(void*))) { |
1785 | debug_tcp("send padding digest 0x%x" | 1692 | tcp_ctask->r2t = r2t; |
1786 | "fail!\n", tcp_ctask->immdigest); | 1693 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; |
1787 | return rc; | 1694 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; |
1788 | } | 1695 | spin_unlock_bh(&session->lock); |
1789 | debug_tcp("done with padding, digest 0x%x\n", | 1696 | goto send_hdr; |
1790 | tcp_ctask->datadigest); | ||
1791 | } else { | ||
1792 | rc = iscsi_digest_final_send(conn, ctask, | ||
1793 | &dtask->digestbuf, | ||
1794 | &dtask->digest, 1); | ||
1795 | if (rc) { | ||
1796 | debug_tcp("send padding digest 0x%x" | ||
1797 | "fail\n", dtask->digest); | ||
1798 | return rc; | ||
1799 | } | ||
1800 | debug_tcp("done with padding, digest 0x%x\n", | ||
1801 | dtask->digest); | ||
1802 | } | 1697 | } |
1698 | spin_unlock_bh(&session->lock); | ||
1803 | } | 1699 | } |
1804 | |||
1805 | return 0; | 1700 | return 0; |
1806 | } | 1701 | } |
1807 | 1702 | ||
@@ -1821,85 +1716,30 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1821 | return rc; | 1716 | return rc; |
1822 | 1717 | ||
1823 | if (tcp_ctask->xmstate & XMSTATE_R_HDR) | 1718 | if (tcp_ctask->xmstate & XMSTATE_R_HDR) |
1824 | return handle_xmstate_r_hdr(conn, tcp_ctask); | 1719 | return iscsi_send_read_hdr(conn, tcp_ctask); |
1825 | 1720 | ||
1826 | if (tcp_ctask->xmstate & XMSTATE_W_HDR) { | 1721 | if (tcp_ctask->xmstate & XMSTATE_W_HDR) { |
1827 | rc = handle_xmstate_w_hdr(conn, ctask); | 1722 | rc = iscsi_send_write_hdr(conn, ctask); |
1828 | if (rc) | ||
1829 | return rc; | ||
1830 | } | ||
1831 | |||
1832 | /* XXX: for data digest xmit recover */ | ||
1833 | if (tcp_ctask->xmstate & XMSTATE_DATA_DIGEST) { | ||
1834 | rc = handle_xmstate_data_digest(conn, ctask); | ||
1835 | if (rc) | 1723 | if (rc) |
1836 | return rc; | 1724 | return rc; |
1837 | } | 1725 | } |
1838 | 1726 | ||
1839 | if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { | 1727 | if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { |
1840 | rc = handle_xmstate_imm_data(conn, ctask); | 1728 | rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, |
1729 | &tcp_ctask->sent, &ctask->imm_count, | ||
1730 | &tcp_ctask->immbuf, &tcp_ctask->immdigest); | ||
1841 | if (rc) | 1731 | if (rc) |
1842 | return rc; | 1732 | return rc; |
1733 | tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; | ||
1843 | } | 1734 | } |
1844 | 1735 | ||
1845 | if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { | 1736 | rc = iscsi_send_unsol_pdu(conn, ctask); |
1846 | BUG_ON(!ctask->unsol_count); | 1737 | if (rc) |
1847 | tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; | 1738 | return rc; |
1848 | unsolicit_head_again: | ||
1849 | rc = handle_xmstate_uns_hdr(conn, ctask); | ||
1850 | if (rc) | ||
1851 | return rc; | ||
1852 | } | ||
1853 | |||
1854 | if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { | ||
1855 | rc = handle_xmstate_uns_data(conn, ctask); | ||
1856 | if (rc == 1) | ||
1857 | goto unsolicit_head_again; | ||
1858 | else if (rc) | ||
1859 | return rc; | ||
1860 | goto done; | ||
1861 | } | ||
1862 | |||
1863 | if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { | ||
1864 | struct iscsi_r2t_info *r2t; | ||
1865 | |||
1866 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; | ||
1867 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; | ||
1868 | if (!tcp_ctask->r2t) | ||
1869 | __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, | ||
1870 | sizeof(void*)); | ||
1871 | solicit_head_again: | ||
1872 | r2t = tcp_ctask->r2t; | ||
1873 | if (conn->hdrdgst_en) | ||
1874 | iscsi_hdr_digest(conn, &r2t->headbuf, | ||
1875 | (u8*)r2t->dtask.hdrext); | ||
1876 | rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); | ||
1877 | if (rc) { | ||
1878 | tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; | ||
1879 | tcp_ctask->xmstate |= XMSTATE_SOL_HDR; | ||
1880 | return rc; | ||
1881 | } | ||
1882 | |||
1883 | debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n", | ||
1884 | r2t->solicit_datasn - 1, ctask->itt, r2t->data_count, | ||
1885 | r2t->sent); | ||
1886 | } | ||
1887 | |||
1888 | if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { | ||
1889 | rc = handle_xmstate_sol_data(conn, ctask); | ||
1890 | if (rc == 1) | ||
1891 | goto solicit_head_again; | ||
1892 | if (rc) | ||
1893 | return rc; | ||
1894 | } | ||
1895 | 1739 | ||
1896 | done: | 1740 | rc = iscsi_send_sol_pdu(conn, ctask); |
1897 | /* | 1741 | if (rc) |
1898 | * Last thing to check is whether we need to send write | 1742 | return rc; |
1899 | * padding. Note that we check for xmstate equality, not just the bit. | ||
1900 | */ | ||
1901 | if (tcp_ctask->xmstate == XMSTATE_W_PAD) | ||
1902 | rc = handle_xmstate_w_pad(conn, ctask); | ||
1903 | 1743 | ||
1904 | return rc; | 1744 | return rc; |
1905 | } | 1745 | } |
@@ -1931,8 +1771,24 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1931 | /* initial operational parameters */ | 1771 | /* initial operational parameters */ |
1932 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); | 1772 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); |
1933 | 1773 | ||
1774 | tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, | ||
1775 | CRYPTO_ALG_ASYNC); | ||
1776 | tcp_conn->tx_hash.flags = 0; | ||
1777 | if (!tcp_conn->tx_hash.tfm) | ||
1778 | goto free_tcp_conn; | ||
1779 | |||
1780 | tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, | ||
1781 | CRYPTO_ALG_ASYNC); | ||
1782 | tcp_conn->rx_hash.flags = 0; | ||
1783 | if (!tcp_conn->rx_hash.tfm) | ||
1784 | goto free_tx_tfm; | ||
1785 | |||
1934 | return cls_conn; | 1786 | return cls_conn; |
1935 | 1787 | ||
1788 | free_tx_tfm: | ||
1789 | crypto_free_hash(tcp_conn->tx_hash.tfm); | ||
1790 | free_tcp_conn: | ||
1791 | kfree(tcp_conn); | ||
1936 | tcp_conn_alloc_fail: | 1792 | tcp_conn_alloc_fail: |
1937 | iscsi_conn_teardown(cls_conn); | 1793 | iscsi_conn_teardown(cls_conn); |
1938 | return NULL; | 1794 | return NULL; |
@@ -1970,14 +1826,10 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) | |||
1970 | 1826 | ||
1971 | /* now free tcp_conn */ | 1827 | /* now free tcp_conn */ |
1972 | if (digest) { | 1828 | if (digest) { |
1973 | if (tcp_conn->tx_tfm) | 1829 | if (tcp_conn->tx_hash.tfm) |
1974 | crypto_free_hash(tcp_conn->tx_tfm); | 1830 | crypto_free_hash(tcp_conn->tx_hash.tfm); |
1975 | if (tcp_conn->rx_tfm) | 1831 | if (tcp_conn->rx_hash.tfm) |
1976 | crypto_free_hash(tcp_conn->rx_tfm); | 1832 | crypto_free_hash(tcp_conn->rx_hash.tfm); |
1977 | if (tcp_conn->data_tx_hash.tfm) | ||
1978 | crypto_free_hash(tcp_conn->data_tx_hash.tfm); | ||
1979 | if (tcp_conn->data_rx_hash.tfm) | ||
1980 | crypto_free_hash(tcp_conn->data_rx_hash.tfm); | ||
1981 | } | 1833 | } |
1982 | 1834 | ||
1983 | kfree(tcp_conn); | 1835 | kfree(tcp_conn); |
@@ -1987,9 +1839,11 @@ static void | |||
1987 | iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | 1839 | iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) |
1988 | { | 1840 | { |
1989 | struct iscsi_conn *conn = cls_conn->dd_data; | 1841 | struct iscsi_conn *conn = cls_conn->dd_data; |
1842 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
1990 | 1843 | ||
1991 | iscsi_conn_stop(cls_conn, flag); | 1844 | iscsi_conn_stop(cls_conn, flag); |
1992 | iscsi_tcp_release_conn(conn); | 1845 | iscsi_tcp_release_conn(conn); |
1846 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); | ||
1993 | } | 1847 | } |
1994 | 1848 | ||
1995 | static int | 1849 | static int |
@@ -2135,52 +1989,11 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, | |||
2135 | case ISCSI_PARAM_HDRDGST_EN: | 1989 | case ISCSI_PARAM_HDRDGST_EN: |
2136 | iscsi_set_param(cls_conn, param, buf, buflen); | 1990 | iscsi_set_param(cls_conn, param, buf, buflen); |
2137 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); | 1991 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); |
2138 | if (conn->hdrdgst_en) { | 1992 | if (conn->hdrdgst_en) |
2139 | tcp_conn->hdr_size += sizeof(__u32); | 1993 | tcp_conn->hdr_size += sizeof(__u32); |
2140 | if (!tcp_conn->tx_tfm) | ||
2141 | tcp_conn->tx_tfm = | ||
2142 | crypto_alloc_hash("crc32c", 0, | ||
2143 | CRYPTO_ALG_ASYNC); | ||
2144 | if (IS_ERR(tcp_conn->tx_tfm)) | ||
2145 | return PTR_ERR(tcp_conn->tx_tfm); | ||
2146 | if (!tcp_conn->rx_tfm) | ||
2147 | tcp_conn->rx_tfm = | ||
2148 | crypto_alloc_hash("crc32c", 0, | ||
2149 | CRYPTO_ALG_ASYNC); | ||
2150 | if (IS_ERR(tcp_conn->rx_tfm)) { | ||
2151 | crypto_free_hash(tcp_conn->tx_tfm); | ||
2152 | return PTR_ERR(tcp_conn->rx_tfm); | ||
2153 | } | ||
2154 | } else { | ||
2155 | if (tcp_conn->tx_tfm) | ||
2156 | crypto_free_hash(tcp_conn->tx_tfm); | ||
2157 | if (tcp_conn->rx_tfm) | ||
2158 | crypto_free_hash(tcp_conn->rx_tfm); | ||
2159 | } | ||
2160 | break; | 1994 | break; |
2161 | case ISCSI_PARAM_DATADGST_EN: | 1995 | case ISCSI_PARAM_DATADGST_EN: |
2162 | iscsi_set_param(cls_conn, param, buf, buflen); | 1996 | iscsi_set_param(cls_conn, param, buf, buflen); |
2163 | if (conn->datadgst_en) { | ||
2164 | if (!tcp_conn->data_tx_hash.tfm) | ||
2165 | tcp_conn->data_tx_hash.tfm = | ||
2166 | crypto_alloc_hash("crc32c", 0, | ||
2167 | CRYPTO_ALG_ASYNC); | ||
2168 | if (IS_ERR(tcp_conn->data_tx_hash.tfm)) | ||
2169 | return PTR_ERR(tcp_conn->data_tx_hash.tfm); | ||
2170 | if (!tcp_conn->data_rx_hash.tfm) | ||
2171 | tcp_conn->data_rx_hash.tfm = | ||
2172 | crypto_alloc_hash("crc32c", 0, | ||
2173 | CRYPTO_ALG_ASYNC); | ||
2174 | if (IS_ERR(tcp_conn->data_rx_hash.tfm)) { | ||
2175 | crypto_free_hash(tcp_conn->data_tx_hash.tfm); | ||
2176 | return PTR_ERR(tcp_conn->data_rx_hash.tfm); | ||
2177 | } | ||
2178 | } else { | ||
2179 | if (tcp_conn->data_tx_hash.tfm) | ||
2180 | crypto_free_hash(tcp_conn->data_tx_hash.tfm); | ||
2181 | if (tcp_conn->data_rx_hash.tfm) | ||
2182 | crypto_free_hash(tcp_conn->data_rx_hash.tfm); | ||
2183 | } | ||
2184 | tcp_conn->sendpage = conn->datadgst_en ? | 1997 | tcp_conn->sendpage = conn->datadgst_en ? |
2185 | sock_no_sendpage : tcp_conn->sock->ops->sendpage; | 1998 | sock_no_sendpage : tcp_conn->sock->ops->sendpage; |
2186 | break; | 1999 | break; |