aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2008-04-18 11:11:52 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-18 12:53:00 -0400
commitc07d444407de63b2f414a8be9428f88cadba503f (patch)
tree4eabbd7adb9130392beb306cc9f1633258749851 /drivers/scsi/libiscsi.c
parent38d1c069db8c87eb6cb10ca1ede9d9b673531ddd (diff)
[SCSI] iscsi: bidi support at the generic libiscsi level
- prepare the additional bidi_read rlength header. - access the right scsi_in() and/or scsi_out() side of things. also for resid. - Handle BIDI underflow overflow from target 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/scsi/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c85
1 files changed, 70 insertions, 15 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 2f6b0955ff01..010c1b9b178c 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -176,6 +176,31 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
176 return 0; 176 return 0;
177} 177}
178 178
179static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
180{
181 struct scsi_cmnd *sc = ctask->sc;
182 struct iscsi_rlength_ahdr *rlen_ahdr;
183 int rc;
184
185 rlen_ahdr = iscsi_next_hdr(ctask);
186 rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
187 if (rc)
188 return rc;
189
190 rlen_ahdr->ahslength =
191 cpu_to_be16(sizeof(rlen_ahdr->read_length) +
192 sizeof(rlen_ahdr->reserved));
193 rlen_ahdr->ahstype = ISCSI_AHSTYPE_RLENGTH;
194 rlen_ahdr->reserved = 0;
195 rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
196
197 debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
198 "rlen_ahdr->ahslength(%d)\n",
199 be32_to_cpu(rlen_ahdr->read_length),
200 be16_to_cpu(rlen_ahdr->ahslength));
201 return 0;
202}
203
179/** 204/**
180 * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu 205 * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
181 * @ctask: iscsi cmd task 206 * @ctask: iscsi cmd task
@@ -200,7 +225,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
200 hdr->flags = ISCSI_ATTR_SIMPLE; 225 hdr->flags = ISCSI_ATTR_SIMPLE;
201 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); 226 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
202 hdr->itt = build_itt(ctask->itt, session->age); 227 hdr->itt = build_itt(ctask->itt, session->age);
203 hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
204 hdr->cmdsn = cpu_to_be32(session->cmdsn); 228 hdr->cmdsn = cpu_to_be32(session->cmdsn);
205 session->cmdsn++; 229 session->cmdsn++;
206 hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); 230 hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
@@ -216,7 +240,15 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
216 memcpy(hdr->cdb, sc->cmnd, cmd_len); 240 memcpy(hdr->cdb, sc->cmnd, cmd_len);
217 241
218 ctask->imm_count = 0; 242 ctask->imm_count = 0;
243 if (scsi_bidi_cmnd(sc)) {
244 hdr->flags |= ISCSI_FLAG_CMD_READ;
245 rc = iscsi_prep_bidi_ahs(ctask);
246 if (rc)
247 return rc;
248 }
219 if (sc->sc_data_direction == DMA_TO_DEVICE) { 249 if (sc->sc_data_direction == DMA_TO_DEVICE) {
250 unsigned out_len = scsi_out(sc)->length;
251 hdr->data_length = cpu_to_be32(out_len);
220 hdr->flags |= ISCSI_FLAG_CMD_WRITE; 252 hdr->flags |= ISCSI_FLAG_CMD_WRITE;
221 /* 253 /*
222 * Write counters: 254 * Write counters:
@@ -237,19 +269,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
237 ctask->unsol_datasn = 0; 269 ctask->unsol_datasn = 0;
238 270
239 if (session->imm_data_en) { 271 if (session->imm_data_en) {
240 if (scsi_bufflen(sc) >= session->first_burst) 272 if (out_len >= session->first_burst)
241 ctask->imm_count = min(session->first_burst, 273 ctask->imm_count = min(session->first_burst,
242 conn->max_xmit_dlength); 274 conn->max_xmit_dlength);
243 else 275 else
244 ctask->imm_count = min(scsi_bufflen(sc), 276 ctask->imm_count = min(out_len,
245 conn->max_xmit_dlength); 277 conn->max_xmit_dlength);
246 hton24(hdr->dlength, ctask->imm_count); 278 hton24(hdr->dlength, ctask->imm_count);
247 } else 279 } else
248 zero_data(hdr->dlength); 280 zero_data(hdr->dlength);
249 281
250 if (!session->initial_r2t_en) { 282 if (!session->initial_r2t_en) {
251 ctask->unsol_count = min((session->first_burst), 283 ctask->unsol_count = min(session->first_burst, out_len)
252 (scsi_bufflen(sc))) - ctask->imm_count; 284 - ctask->imm_count;
253 ctask->unsol_offset = ctask->imm_count; 285 ctask->unsol_offset = ctask->imm_count;
254 } 286 }
255 287
@@ -259,6 +291,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
259 } else { 291 } else {
260 hdr->flags |= ISCSI_FLAG_CMD_FINAL; 292 hdr->flags |= ISCSI_FLAG_CMD_FINAL;
261 zero_data(hdr->dlength); 293 zero_data(hdr->dlength);
294 hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
262 295
263 if (sc->sc_data_direction == DMA_FROM_DEVICE) 296 if (sc->sc_data_direction == DMA_FROM_DEVICE)
264 hdr->flags |= ISCSI_FLAG_CMD_READ; 297 hdr->flags |= ISCSI_FLAG_CMD_READ;
@@ -277,10 +310,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
277 return EIO; 310 return EIO;
278 311
279 conn->scsicmd_pdus_cnt++; 312 conn->scsicmd_pdus_cnt++;
280 debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d " 313 debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
281 "cmdsn %d win %d]\n", 314 "len %d bidi_len %d cmdsn %d win %d]\n",
282 sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", 315 scsi_bidi_cmnd(sc) ? "bidirectional" :
283 conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc), 316 sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
317 conn->id, sc, sc->cmnd[0], ctask->itt,
318 scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
284 session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); 319 session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
285 return 0; 320 return 0;
286} 321}
@@ -343,7 +378,12 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
343 conn->session->tt->cleanup_cmd_task(conn, ctask); 378 conn->session->tt->cleanup_cmd_task(conn, ctask);
344 379
345 sc->result = err; 380 sc->result = err;
346 scsi_set_resid(sc, scsi_bufflen(sc)); 381 if (!scsi_bidi_cmnd(sc))
382 scsi_set_resid(sc, scsi_bufflen(sc));
383 else {
384 scsi_out(sc)->resid = scsi_out(sc)->length;
385 scsi_in(sc)->resid = scsi_in(sc)->length;
386 }
347 if (conn->ctask == ctask) 387 if (conn->ctask == ctask)
348 conn->ctask = NULL; 388 conn->ctask = NULL;
349 /* release ref from queuecommand */ 389 /* release ref from queuecommand */
@@ -478,6 +518,18 @@ invalid_datalen:
478 min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); 518 min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
479 } 519 }
480 520
521 if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
522 ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
523 int res_count = be32_to_cpu(rhdr->bi_residual_count);
524
525 if (scsi_bidi_cmnd(sc) && res_count > 0 &&
526 (rhdr->flags & ISCSI_FLAG_CMD_BIDI_OVERFLOW ||
527 res_count <= scsi_in(sc)->length))
528 scsi_in(sc)->resid = res_count;
529 else
530 sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
531 }
532
481 if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW | 533 if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
482 ISCSI_FLAG_CMD_OVERFLOW)) { 534 ISCSI_FLAG_CMD_OVERFLOW)) {
483 int res_count = be32_to_cpu(rhdr->residual_count); 535 int res_count = be32_to_cpu(rhdr->residual_count);
@@ -485,13 +537,11 @@ invalid_datalen:
485 if (res_count > 0 && 537 if (res_count > 0 &&
486 (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW || 538 (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
487 res_count <= scsi_bufflen(sc))) 539 res_count <= scsi_bufflen(sc)))
540 /* write side for bidi or uni-io set_resid */
488 scsi_set_resid(sc, res_count); 541 scsi_set_resid(sc, res_count);
489 else 542 else
490 sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; 543 sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
491 } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW | 544 }
492 ISCSI_FLAG_CMD_BIDI_OVERFLOW))
493 sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
494
495out: 545out:
496 debug_scsi("done [sc %lx res %d itt 0x%x]\n", 546 debug_scsi("done [sc %lx res %d itt 0x%x]\n",
497 (long)sc, sc->result, ctask->itt); 547 (long)sc, sc->result, ctask->itt);
@@ -1147,7 +1197,12 @@ reject:
1147fault: 1197fault:
1148 spin_unlock(&session->lock); 1198 spin_unlock(&session->lock);
1149 debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); 1199 debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
1150 scsi_set_resid(sc, scsi_bufflen(sc)); 1200 if (!scsi_bidi_cmnd(sc))
1201 scsi_set_resid(sc, scsi_bufflen(sc));
1202 else {
1203 scsi_out(sc)->resid = scsi_out(sc)->length;
1204 scsi_in(sc)->resid = scsi_in(sc)->length;
1205 }
1151 sc->scsi_done(sc); 1206 sc->scsi_done(sc);
1152 spin_lock(host->host_lock); 1207 spin_lock(host->host_lock);
1153 return 0; 1208 return 0;