aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2008-04-18 11:11:51 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-18 12:51:19 -0400
commit38d1c069db8c87eb6cb10ca1ede9d9b673531ddd (patch)
treeb5e823e2225620f0db342e70e107831e505b9276 /drivers
parent57b7658aed76f1763416878ead9be4ffa288b7a3 (diff)
[SCSI] iscsi: extended cdb support
Support for extended CDBs in iscsi. All we need is to check if command spills over 16 bytes then allocate an iscsi-extended-header for the leftovers. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Reviewed-by: Pete Wyckoff <pw@osc.edu> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libiscsi.c55
1 files changed, 50 insertions, 5 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) {