diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 55 |
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 | */ | ||
143 | static 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) { |