diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-12-02 01:32:13 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-12-29 12:24:22 -0500 |
commit | 262ef63627977acb7d8dd38c4f0f290bf49fbbfd (patch) | |
tree | fc8e01280968470f2d3d122614508fe5e402e0a2 /drivers/scsi/libiscsi.c | |
parent | 38e1a8f5479d7d75a68d797c7159f5b7e2ef44e4 (diff) |
[SCSI] libiscsi: allow drivers to modify the itt sent to the target
bnx2i and cxgb3i need to encode LLD info in the itt so that
the firmware/hardware can process the pdu. This patch allows
the LLDs to encode info in the task->hdr->itt that they
setup in the alloc_pdu callout (any resources that are allocated
can be freed with the pdu in the cleanup_task callout). If
the LLD encodes info in the itt they should implement a
parse_pdu_itt callout. If parse_pdu_itt is not implemented
libiscsi will do the right thing for the LLD.
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.c | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c1bb74052aed..6c4034b1561c 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -222,12 +222,14 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
222 | struct scsi_cmnd *sc = task->sc; | 222 | struct scsi_cmnd *sc = task->sc; |
223 | struct iscsi_cmd *hdr; | 223 | struct iscsi_cmd *hdr; |
224 | unsigned hdrlength, cmd_len; | 224 | unsigned hdrlength, cmd_len; |
225 | itt_t itt; | ||
225 | int rc; | 226 | int rc; |
226 | 227 | ||
227 | rc = conn->session->tt->alloc_pdu(task); | 228 | rc = conn->session->tt->alloc_pdu(task); |
228 | if (rc) | 229 | if (rc) |
229 | return rc; | 230 | return rc; |
230 | hdr = (struct iscsi_cmd *) task->hdr; | 231 | hdr = (struct iscsi_cmd *) task->hdr; |
232 | itt = hdr->itt; | ||
231 | memset(hdr, 0, sizeof(*hdr)); | 233 | memset(hdr, 0, sizeof(*hdr)); |
232 | 234 | ||
233 | task->hdr_len = 0; | 235 | task->hdr_len = 0; |
@@ -238,7 +240,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
238 | hdr->flags = ISCSI_ATTR_SIMPLE; | 240 | hdr->flags = ISCSI_ATTR_SIMPLE; |
239 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); | 241 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); |
240 | memcpy(task->lun, hdr->lun, sizeof(task->lun)); | 242 | memcpy(task->lun, hdr->lun, sizeof(task->lun)); |
241 | hdr->itt = task->hdr_itt = build_itt(task->itt, session->age); | 243 | if (session->tt->parse_pdu_itt) |
244 | hdr->itt = task->hdr_itt = itt; | ||
245 | else | ||
246 | hdr->itt = task->hdr_itt = build_itt(task->itt, | ||
247 | task->conn->session->age); | ||
242 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); | 248 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); |
243 | session->cmdsn++; | 249 | session->cmdsn++; |
244 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); | 250 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); |
@@ -457,7 +463,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
457 | */ | 463 | */ |
458 | nop->cmdsn = cpu_to_be32(session->cmdsn); | 464 | nop->cmdsn = cpu_to_be32(session->cmdsn); |
459 | if (hdr->itt != RESERVED_ITT) { | 465 | if (hdr->itt != RESERVED_ITT) { |
460 | hdr->itt = build_itt(task->itt, session->age); | ||
461 | /* | 466 | /* |
462 | * TODO: We always use immediate, so we never hit this. | 467 | * TODO: We always use immediate, so we never hit this. |
463 | * If we start to send tmfs or nops as non-immediate then | 468 | * If we start to send tmfs or nops as non-immediate then |
@@ -490,6 +495,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
490 | { | 495 | { |
491 | struct iscsi_session *session = conn->session; | 496 | struct iscsi_session *session = conn->session; |
492 | struct iscsi_task *task; | 497 | struct iscsi_task *task; |
498 | itt_t itt; | ||
493 | 499 | ||
494 | if (session->state == ISCSI_STATE_TERMINATE) | 500 | if (session->state == ISCSI_STATE_TERMINATE) |
495 | return NULL; | 501 | return NULL; |
@@ -531,9 +537,18 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
531 | "pdu for mgmt task.\n"); | 537 | "pdu for mgmt task.\n"); |
532 | goto requeue_task; | 538 | goto requeue_task; |
533 | } | 539 | } |
540 | itt = task->hdr->itt; | ||
534 | task->hdr_len = sizeof(struct iscsi_hdr); | 541 | task->hdr_len = sizeof(struct iscsi_hdr); |
535 | |||
536 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); | 542 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); |
543 | |||
544 | if (hdr->itt != RESERVED_ITT) { | ||
545 | if (session->tt->parse_pdu_itt) | ||
546 | task->hdr->itt = itt; | ||
547 | else | ||
548 | task->hdr->itt = build_itt(task->itt, | ||
549 | task->conn->session->age); | ||
550 | } | ||
551 | |||
537 | INIT_LIST_HEAD(&task->running); | 552 | INIT_LIST_HEAD(&task->running); |
538 | list_add_tail(&task->running, &conn->mgmtqueue); | 553 | list_add_tail(&task->running, &conn->mgmtqueue); |
539 | 554 | ||
@@ -745,7 +760,6 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
745 | { | 760 | { |
746 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; | 761 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; |
747 | struct iscsi_hdr rejected_pdu; | 762 | struct iscsi_hdr rejected_pdu; |
748 | uint32_t itt; | ||
749 | 763 | ||
750 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; | 764 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; |
751 | 765 | ||
@@ -755,10 +769,9 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
755 | 769 | ||
756 | if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { | 770 | if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { |
757 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); | 771 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); |
758 | itt = get_itt(rejected_pdu.itt); | ||
759 | iscsi_conn_printk(KERN_ERR, conn, | 772 | iscsi_conn_printk(KERN_ERR, conn, |
760 | "itt 0x%x had pdu (op 0x%x) rejected " | 773 | "pdu (op 0x%x) rejected " |
761 | "due to DataDigest error.\n", itt, | 774 | "due to DataDigest error.\n", |
762 | rejected_pdu.opcode); | 775 | rejected_pdu.opcode); |
763 | } | 776 | } |
764 | } | 777 | } |
@@ -778,12 +791,15 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
778 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) | 791 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) |
779 | { | 792 | { |
780 | struct iscsi_session *session = conn->session; | 793 | struct iscsi_session *session = conn->session; |
781 | uint32_t i; | 794 | int i; |
782 | 795 | ||
783 | if (itt == RESERVED_ITT) | 796 | if (itt == RESERVED_ITT) |
784 | return NULL; | 797 | return NULL; |
785 | 798 | ||
786 | i = get_itt(itt); | 799 | if (session->tt->parse_pdu_itt) |
800 | session->tt->parse_pdu_itt(conn, itt, &i, NULL); | ||
801 | else | ||
802 | i = get_itt(itt); | ||
787 | if (i >= session->cmds_max) | 803 | if (i >= session->cmds_max) |
788 | return NULL; | 804 | return NULL; |
789 | 805 | ||
@@ -958,20 +974,25 @@ EXPORT_SYMBOL_GPL(iscsi_complete_pdu); | |||
958 | int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) | 974 | int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) |
959 | { | 975 | { |
960 | struct iscsi_session *session = conn->session; | 976 | struct iscsi_session *session = conn->session; |
961 | uint32_t i; | 977 | int age = 0, i = 0; |
962 | 978 | ||
963 | if (itt == RESERVED_ITT) | 979 | if (itt == RESERVED_ITT) |
964 | return 0; | 980 | return 0; |
965 | 981 | ||
966 | if (((__force u32)itt & ISCSI_AGE_MASK) != | 982 | if (session->tt->parse_pdu_itt) |
967 | (session->age << ISCSI_AGE_SHIFT)) { | 983 | session->tt->parse_pdu_itt(conn, itt, &i, &age); |
984 | else { | ||
985 | i = get_itt(itt); | ||
986 | age = ((__force u32)itt >> ISCSI_AGE_SHIFT) & ISCSI_AGE_MASK; | ||
987 | } | ||
988 | |||
989 | if (age != session->age) { | ||
968 | iscsi_conn_printk(KERN_ERR, conn, | 990 | iscsi_conn_printk(KERN_ERR, conn, |
969 | "received itt %x expected session age (%x)\n", | 991 | "received itt %x expected session age (%x)\n", |
970 | (__force u32)itt, session->age); | 992 | (__force u32)itt, session->age); |
971 | return ISCSI_ERR_BAD_ITT; | 993 | return ISCSI_ERR_BAD_ITT; |
972 | } | 994 | } |
973 | 995 | ||
974 | i = get_itt(itt); | ||
975 | if (i >= session->cmds_max) { | 996 | if (i >= session->cmds_max) { |
976 | iscsi_conn_printk(KERN_ERR, conn, | 997 | iscsi_conn_printk(KERN_ERR, conn, |
977 | "received invalid itt index %u (max cmds " | 998 | "received invalid itt index %u (max cmds " |