aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libiscsi.c47
-rw-r--r--include/scsi/libiscsi.h5
-rw-r--r--include/scsi/scsi_transport_iscsi.h3
3 files changed, 40 insertions, 15 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,
778static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) 791static 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);
958int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) 974int 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 "
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 51500573c0b8..7360e1916e75 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -30,6 +30,7 @@
30#include <linux/workqueue.h> 30#include <linux/workqueue.h>
31#include <scsi/iscsi_proto.h> 31#include <scsi/iscsi_proto.h>
32#include <scsi/iscsi_if.h> 32#include <scsi/iscsi_if.h>
33#include <scsi/scsi_transport_iscsi.h>
33 34
34struct scsi_transport_template; 35struct scsi_transport_template;
35struct scsi_host_template; 36struct scsi_host_template;
@@ -70,12 +71,12 @@ enum {
70/* Connection suspend "bit" */ 71/* Connection suspend "bit" */
71#define ISCSI_SUSPEND_BIT 1 72#define ISCSI_SUSPEND_BIT 1
72 73
73#define ISCSI_ITT_MASK (0x1fff) 74#define ISCSI_ITT_MASK 0x1fff
74#define ISCSI_TOTAL_CMDS_MAX 4096 75#define ISCSI_TOTAL_CMDS_MAX 4096
75/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */ 76/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */
76#define ISCSI_TOTAL_CMDS_MIN 16 77#define ISCSI_TOTAL_CMDS_MIN 16
77#define ISCSI_AGE_SHIFT 28 78#define ISCSI_AGE_SHIFT 28
78#define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) 79#define ISCSI_AGE_MASK 0xf
79 80
80#define ISCSI_ADDRESS_BUF_LEN 64 81#define ISCSI_ADDRESS_BUF_LEN 64
81 82
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index c928234c018f..e13cb20f1eae 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -122,6 +122,9 @@ struct iscsi_transport {
122 int (*xmit_pdu) (struct iscsi_task *task); 122 int (*xmit_pdu) (struct iscsi_task *task);
123 int (*init_pdu) (struct iscsi_task *task, unsigned int offset, 123 int (*init_pdu) (struct iscsi_task *task, unsigned int offset,
124 unsigned int count); 124 unsigned int count);
125 void (*parse_pdu_itt) (struct iscsi_conn *conn, itt_t itt,
126 int *index, int *age);
127
125 void (*session_recovery_timedout) (struct iscsi_cls_session *session); 128 void (*session_recovery_timedout) (struct iscsi_cls_session *session);
126 struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr, 129 struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr,
127 int non_blocking); 130 int non_blocking);