diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2007-12-13 06:50:53 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-30 14:03:41 -0500 |
commit | 6f9a35e2dafa0f855ab051c11bdbf739745ff6f5 (patch) | |
tree | 5ca273c98b61a4d329653ef30faa2c0414eccd2b /drivers/scsi/scsi_error.c | |
parent | 30b0c37b27485a9cb897bfe3824f6f517b8c80d6 (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.c | 3 |
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 | } |
678 | EXPORT_SYMBOL(scsi_eh_restore_cmnd); | 681 | EXPORT_SYMBOL(scsi_eh_restore_cmnd); |