aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_error.c
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2007-12-13 06:50:53 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-30 14:03:41 -0500
commit6f9a35e2dafa0f855ab051c11bdbf739745ff6f5 (patch)
tree5ca273c98b61a4d329653ef30faa2c0414eccd2b /drivers/scsi/scsi_error.c
parent30b0c37b27485a9cb897bfe3824f6f517b8c80d6 (diff)
[SCSI] bidirectional command support
At the block level bidi request uses req->next_rq pointer for a second bidi_read request. At Scsi-midlayer a second scsi_data_buffer structure is used for the bidi_read part. This bidi scsi_data_buffer is put on request->next_rq->special. Struct scsi_cmnd is not changed. - Define scsi_bidi_cmnd() to return true if it is a bidi request and a second sgtable was allocated. - Define scsi_in()/scsi_out() to return the in or out scsi_data_buffer from this command This API is to isolate users from the mechanics of bidi. - Define scsi_end_bidi_request() to do what scsi_end_request() does but for a bidi request. This is necessary because bidi commands are a bit tricky here. (See comments in body) - scsi_release_buffers() will also release the bidi_read scsi_data_buffer - scsi_io_completion() on bidi commands will now call scsi_end_bidi_request() and return. - The previous work done in scsi_init_io() is now done in a new scsi_init_sgtable() (which is 99% identical to old scsi_init_io()) The new scsi_init_io() will call the above twice if needed also for the bidi_read command. Only at this point is a command bidi. - In scsi_error.c at scsi_eh_prep/restore_cmnd() make sure bidi-lld is not confused by a get-sense command that looks like bidi. This is done by puting NULL at request->next_rq, and restoring. [jejb: update to sg_table and resolve conflicts also update to blk-end-request and resolve conflicts] Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r--drivers/scsi/scsi_error.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 4f4edc388c07..045a0868fc7b 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -618,9 +618,11 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
618 memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd)); 618 memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
619 ses->data_direction = scmd->sc_data_direction; 619 ses->data_direction = scmd->sc_data_direction;
620 ses->sdb = scmd->sdb; 620 ses->sdb = scmd->sdb;
621 ses->next_rq = scmd->request->next_rq;
621 ses->result = scmd->result; 622 ses->result = scmd->result;
622 623
623 memset(&scmd->sdb, 0, sizeof(scmd->sdb)); 624 memset(&scmd->sdb, 0, sizeof(scmd->sdb));
625 scmd->request->next_rq = NULL;
624 626
625 if (sense_bytes) { 627 if (sense_bytes) {
626 scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE, 628 scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
@@ -673,6 +675,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
673 memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd)); 675 memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
674 scmd->sc_data_direction = ses->data_direction; 676 scmd->sc_data_direction = ses->data_direction;
675 scmd->sdb = ses->sdb; 677 scmd->sdb = ses->sdb;
678 scmd->request->next_rq = ses->next_rq;
676 scmd->result = ses->result; 679 scmd->result = ses->result;
677} 680}
678EXPORT_SYMBOL(scsi_eh_restore_cmnd); 681EXPORT_SYMBOL(scsi_eh_restore_cmnd);