diff options
-rw-r--r-- | drivers/scsi/libiscsi.c | 55 | ||||
-rw-r--r-- | include/scsi/iscsi_proto.h | 6 |
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 | */ | ||
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) { |
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 */ |
117 | struct iscsi_cmd { | 118 | struct 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 */ |