aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2007-10-08 10:35:19 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:54:51 -0400
commit55db6c1b8ed52bfc876e87971de8c67c42f36909 (patch)
tree3acfaf8a15c608d7744b826ff081445cc332c0be /drivers/scsi
parent2ca482302f2080e6861eaf753051ac35b6b411ad (diff)
[SCSI] scsi_error: code cleanup before refactoring of scsi_send_eh_cmnd()
- regrouped variables for easier reviewing of next patch - Support of cmnd==NULL in call to scsi_send_eh_cmnd() - In the @sense_bytes case set transfer size to the minimum size of sense_buffer and passed @sense_bytes. cmnd[4] is set accordingly. - REQUEST_SENSE is set into cmnd[0] so if @sense_bytes is not Zero passed @cmnd should be NULL. - Also save/restore resid of failed command. - Adjust caller Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_error.c71
1 files changed, 39 insertions, 32 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index f49feb9351d0..4d535019e04b 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -592,36 +592,39 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
592/** 592/**
593 * scsi_send_eh_cmnd - submit a scsi command as part of error recory 593 * scsi_send_eh_cmnd - submit a scsi command as part of error recory
594 * @scmd: SCSI command structure to hijack 594 * @scmd: SCSI command structure to hijack
595 * @cmnd: CDB to send 595 * @cmnd: CDB to send. Can be NULL if no new cmnd is needed
596 * @cmnd_size: size in bytes of @cmnd 596 * @cmnd_size: size in bytes of @cmnd
597 * @timeout: timeout for this request 597 * @timeout: timeout for this request
598 * @copy_sense: request sense data if set to 1 598 * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
599 * 599 *
600 * This function is used to send a scsi command down to a target device 600 * This function is used to send a scsi command down to a target device
601 * as part of the error recovery process. If @copy_sense is 0 the command 601 * as part of the error recovery process. If @sense_bytes is 0 the command
602 * sent must be one that does not transfer any data. If @copy_sense is 1 602 * sent must be one that does not transfer any data. If @sense_bytes != 0
603 * the command must be REQUEST_SENSE and this functions copies out the 603 * @cmnd is ignored and this functions sets up a REQUEST_SENSE command
604 * sense buffer it got into @scmd->sense_buffer. 604 * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer.
605 * 605 *
606 * Return value: 606 * Return value:
607 * SUCCESS or FAILED or NEEDS_RETRY 607 * SUCCESS or FAILED or NEEDS_RETRY
608 **/ 608 **/
609static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, 609static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
610 int cmnd_size, int timeout, int copy_sense) 610 int cmnd_size, int timeout, unsigned sense_bytes)
611{ 611{
612 struct scsi_device *sdev = scmd->device; 612 struct scsi_device *sdev = scmd->device;
613 struct Scsi_Host *shost = sdev->host; 613 struct Scsi_Host *shost = sdev->host;
614 int old_result = scmd->result;
615 DECLARE_COMPLETION_ONSTACK(done); 614 DECLARE_COMPLETION_ONSTACK(done);
616 unsigned long timeleft; 615 unsigned long timeleft;
617 unsigned long flags; 616 unsigned long flags;
618 struct scatterlist sgl; 617
618 unsigned char old_cmd_len;
619 unsigned char old_cmnd[MAX_COMMAND_SIZE]; 619 unsigned char old_cmnd[MAX_COMMAND_SIZE];
620 enum dma_data_direction old_data_direction; 620 enum dma_data_direction old_data_direction;
621 unsigned short old_use_sg;
622 unsigned char old_cmd_len;
623 unsigned old_bufflen; 621 unsigned old_bufflen;
624 void *old_buffer; 622 void *old_buffer;
623 unsigned short old_use_sg;
624 int old_resid;
625 int old_result;
626
627 struct scatterlist sgl;
625 int rtn; 628 int rtn;
626 629
627 /* 630 /*
@@ -631,35 +634,41 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
631 * we will need to restore these values prior to running the actual 634 * we will need to restore these values prior to running the actual
632 * command. 635 * command.
633 */ 636 */
634 old_buffer = scmd->request_buffer; 637 old_cmd_len = scmd->cmd_len;
635 old_bufflen = scmd->request_bufflen;
636 memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd)); 638 memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd));
637 old_data_direction = scmd->sc_data_direction; 639 old_data_direction = scmd->sc_data_direction;
638 old_cmd_len = scmd->cmd_len; 640 old_bufflen = scmd->request_bufflen;
641 old_buffer = scmd->request_buffer;
639 old_use_sg = scmd->use_sg; 642 old_use_sg = scmd->use_sg;
643 old_resid = scmd->resid;
644 old_result = scmd->result;
640 645
641 memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); 646 if (sense_bytes) {
642 memcpy(scmd->cmnd, cmnd, cmnd_size); 647 scmd->request_bufflen = min_t(unsigned,
643 648 sizeof(scmd->sense_buffer), sense_bytes);
644 if (copy_sense) { 649 sg_init_one(&sgl, scmd->sense_buffer, scmd->request_bufflen);
645 sg_init_one(&sgl, scmd->sense_buffer,
646 sizeof(scmd->sense_buffer));
647
648 scmd->sc_data_direction = DMA_FROM_DEVICE;
649 scmd->request_bufflen = sgl.length;
650 scmd->request_buffer = &sgl; 650 scmd->request_buffer = &sgl;
651 scmd->sc_data_direction = DMA_FROM_DEVICE;
651 scmd->use_sg = 1; 652 scmd->use_sg = 1;
653 memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
654 scmd->cmnd[0] = REQUEST_SENSE;
655 scmd->cmnd[4] = scmd->request_bufflen;
656 scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
652 } else { 657 } else {
653 scmd->request_buffer = NULL; 658 scmd->request_buffer = NULL;
654 scmd->request_bufflen = 0; 659 scmd->request_bufflen = 0;
655 scmd->sc_data_direction = DMA_NONE; 660 scmd->sc_data_direction = DMA_NONE;
656 scmd->use_sg = 0; 661 scmd->use_sg = 0;
662 if (cmnd) {
663 memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
664 memcpy(scmd->cmnd, cmnd, cmnd_size);
665 scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
666 }
657 } 667 }
658 668
659 scmd->underflow = 0; 669 scmd->underflow = 0;
660 scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
661 670
662 if (sdev->scsi_level <= SCSI_2) 671 if (sdev->scsi_level <= SCSI_2 && sdev->scsi_level != SCSI_UNKNOWN)
663 scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) | 672 scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
664 (sdev->lun << 5 & 0xe0); 673 (sdev->lun << 5 & 0xe0);
665 674
@@ -716,12 +725,13 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
716 /* 725 /*
717 * Restore original data 726 * Restore original data
718 */ 727 */
719 scmd->request_buffer = old_buffer; 728 scmd->cmd_len = old_cmd_len;
720 scmd->request_bufflen = old_bufflen;
721 memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd)); 729 memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd));
722 scmd->sc_data_direction = old_data_direction; 730 scmd->sc_data_direction = old_data_direction;
723 scmd->cmd_len = old_cmd_len; 731 scmd->request_bufflen = old_bufflen;
732 scmd->request_buffer = old_buffer;
724 scmd->use_sg = old_use_sg; 733 scmd->use_sg = old_use_sg;
734 scmd->resid = old_resid;
725 scmd->result = old_result; 735 scmd->result = old_result;
726 return rtn; 736 return rtn;
727} 737}
@@ -737,10 +747,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
737 **/ 747 **/
738static int scsi_request_sense(struct scsi_cmnd *scmd) 748static int scsi_request_sense(struct scsi_cmnd *scmd)
739{ 749{
740 static unsigned char generic_sense[6] = 750 return scsi_send_eh_cmnd(scmd, NULL, 0, SENSE_TIMEOUT, ~0);
741 {REQUEST_SENSE, 0, 0, 0, 252, 0};
742
743 return scsi_send_eh_cmnd(scmd, generic_sense, 6, SENSE_TIMEOUT, 1);
744} 751}
745 752
746/** 753/**