aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libiscsi.c55
-rw-r--r--include/scsi/iscsi_proto.h6
2 files changed, 54 insertions, 7 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index bdd7de7da39a..2f6b0955ff01 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -137,6 +137,45 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
137 return 0; 137 return 0;
138} 138}
139 139
140/*
141 * make an extended cdb AHS
142 */
143static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
144{
145 struct scsi_cmnd *cmd = ctask->sc;
146 unsigned rlen, pad_len;
147 unsigned short ahslength;
148 struct iscsi_ecdb_ahdr *ecdb_ahdr;
149 int rc;
150
151 ecdb_ahdr = iscsi_next_hdr(ctask);
152 rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
153
154 BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
155 ahslength = rlen + sizeof(ecdb_ahdr->reserved);
156
157 pad_len = iscsi_padding(rlen);
158
159 rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
160 sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
161 if (rc)
162 return rc;
163
164 if (pad_len)
165 memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
166
167 ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
168 ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
169 ecdb_ahdr->reserved = 0;
170 memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
171
172 debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
173 "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
174 cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
175
176 return 0;
177}
178
140/** 179/**
141 * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu 180 * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
142 * @ctask: iscsi cmd task 181 * @ctask: iscsi cmd task
@@ -150,7 +189,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
150 struct iscsi_session *session = conn->session; 189 struct iscsi_session *session = conn->session;
151 struct iscsi_cmd *hdr = ctask->hdr; 190 struct iscsi_cmd *hdr = ctask->hdr;
152 struct scsi_cmnd *sc = ctask->sc; 191 struct scsi_cmnd *sc = ctask->sc;
153 unsigned hdrlength; 192 unsigned hdrlength, cmd_len;
154 int rc; 193 int rc;
155 194
156 ctask->hdr_len = 0; 195 ctask->hdr_len = 0;
@@ -165,10 +204,16 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
165 hdr->cmdsn = cpu_to_be32(session->cmdsn); 204 hdr->cmdsn = cpu_to_be32(session->cmdsn);
166 session->cmdsn++; 205 session->cmdsn++;
167 hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); 206 hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
168 memcpy(hdr->cdb, sc->cmnd, sc->cmd_len); 207 cmd_len = sc->cmd_len;
169 if (sc->cmd_len < MAX_COMMAND_SIZE) 208 if (cmd_len < ISCSI_CDB_SIZE)
170 memset(&hdr->cdb[sc->cmd_len], 0, 209 memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
171 MAX_COMMAND_SIZE - sc->cmd_len); 210 else if (cmd_len > ISCSI_CDB_SIZE) {
211 rc = iscsi_prep_ecdb_ahs(ctask);
212 if (rc)
213 return rc;
214 cmd_len = ISCSI_CDB_SIZE;
215 }
216 memcpy(hdr->cdb, sc->cmnd, cmd_len);
172 217
173 ctask->imm_count = 0; 218 ctask->imm_count = 0;
174 if (sc->sc_data_direction == DMA_TO_DEVICE) { 219 if (sc->sc_data_direction == DMA_TO_DEVICE) {
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 5ffec8ad6964..e0593bfae622 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -112,6 +112,7 @@ struct iscsi_ahs_hdr {
112 112
113#define ISCSI_AHSTYPE_CDB 1 113#define ISCSI_AHSTYPE_CDB 1
114#define ISCSI_AHSTYPE_RLENGTH 2 114#define ISCSI_AHSTYPE_RLENGTH 2
115#define ISCSI_CDB_SIZE 16
115 116
116/* iSCSI PDU Header */ 117/* iSCSI PDU Header */
117struct iscsi_cmd { 118struct iscsi_cmd {
@@ -125,7 +126,7 @@ struct iscsi_cmd {
125 __be32 data_length; 126 __be32 data_length;
126 __be32 cmdsn; 127 __be32 cmdsn;
127 __be32 exp_statsn; 128 __be32 exp_statsn;
128 uint8_t cdb[16]; /* SCSI Command Block */ 129 uint8_t cdb[ISCSI_CDB_SIZE]; /* SCSI Command Block */
129 /* Additional Data (Command Dependent) */ 130 /* Additional Data (Command Dependent) */
130}; 131};
131 132
@@ -154,7 +155,8 @@ struct iscsi_ecdb_ahdr {
154 __be16 ahslength; /* CDB length - 15, including reserved byte */ 155 __be16 ahslength; /* CDB length - 15, including reserved byte */
155 uint8_t ahstype; 156 uint8_t ahstype;
156 uint8_t reserved; 157 uint8_t reserved;
157 uint8_t ecdb[260 - 16]; /* 4-byte aligned extended CDB spillover */ 158 /* 4-byte aligned extended CDB spillover */
159 uint8_t ecdb[260 - ISCSI_CDB_SIZE];
158}; 160};
159 161
160/* SCSI Response Header */ 162/* SCSI Response Header */