diff options
author | Hannes Reinecke <hare@suse.de> | 2013-04-25 02:10:00 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-10 10:47:44 -0400 |
commit | fc73648a5026dcf228aadc6ab8ca4b868d91c159 (patch) | |
tree | 69120446e56d07168c8971763841ed3aba471ad8 | |
parent | d522844a315233162dd715c620c14ac47110eeca (diff) |
[SCSI] Handle MLQUEUE busy response in scsi_send_eh_cmnd
scsi_send_eh_cmnd() is calling queuecommand() directly, so
it needs to check the return value here.
The only valid return codes for queuecommand() are 'busy'
states, so we need to wait for a bit to allow the LLDD
to recover.
Based on an earlier patch from Wen Xiong.
[jejb: fix confusion between msec and jiffies values and other issues]
[bvanassche: correct stall_for interval]
Cc: Wen Xiong <wenxiong@linux.vnet.ibm.com>
Cc: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/scsi_error.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c1b05a83d403..f43de1e56420 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/blkdev.h> | 26 | #include <linux/blkdev.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/jiffies.h> | ||
28 | 29 | ||
29 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
30 | #include <scsi/scsi_cmnd.h> | 31 | #include <scsi/scsi_cmnd.h> |
@@ -791,32 +792,48 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
791 | struct scsi_device *sdev = scmd->device; | 792 | struct scsi_device *sdev = scmd->device; |
792 | struct Scsi_Host *shost = sdev->host; | 793 | struct Scsi_Host *shost = sdev->host; |
793 | DECLARE_COMPLETION_ONSTACK(done); | 794 | DECLARE_COMPLETION_ONSTACK(done); |
794 | unsigned long timeleft; | 795 | unsigned long timeleft = timeout; |
795 | struct scsi_eh_save ses; | 796 | struct scsi_eh_save ses; |
797 | const unsigned long stall_for = msecs_to_jiffies(100); | ||
796 | int rtn; | 798 | int rtn; |
797 | 799 | ||
800 | retry: | ||
798 | scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes); | 801 | scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes); |
799 | shost->eh_action = &done; | 802 | shost->eh_action = &done; |
800 | 803 | ||
801 | scsi_log_send(scmd); | 804 | scsi_log_send(scmd); |
802 | scmd->scsi_done = scsi_eh_done; | 805 | scmd->scsi_done = scsi_eh_done; |
803 | shost->hostt->queuecommand(shost, scmd); | 806 | rtn = shost->hostt->queuecommand(shost, scmd); |
804 | 807 | if (rtn) { | |
805 | timeleft = wait_for_completion_timeout(&done, timeout); | 808 | if (timeleft > stall_for) { |
809 | scsi_eh_restore_cmnd(scmd, &ses); | ||
810 | timeleft -= stall_for; | ||
811 | msleep(jiffies_to_msecs(stall_for)); | ||
812 | goto retry; | ||
813 | } | ||
814 | /* signal not to enter either branch of the if () below */ | ||
815 | timeleft = 0; | ||
816 | rtn = NEEDS_RETRY; | ||
817 | } else { | ||
818 | timeleft = wait_for_completion_timeout(&done, timeout); | ||
819 | } | ||
806 | 820 | ||
807 | shost->eh_action = NULL; | 821 | shost->eh_action = NULL; |
808 | 822 | ||
809 | scsi_log_completion(scmd, SUCCESS); | 823 | scsi_log_completion(scmd, rtn); |
810 | 824 | ||
811 | SCSI_LOG_ERROR_RECOVERY(3, | 825 | SCSI_LOG_ERROR_RECOVERY(3, |
812 | printk("%s: scmd: %p, timeleft: %ld\n", | 826 | printk("%s: scmd: %p, timeleft: %ld\n", |
813 | __func__, scmd, timeleft)); | 827 | __func__, scmd, timeleft)); |
814 | 828 | ||
815 | /* | 829 | /* |
816 | * If there is time left scsi_eh_done got called, and we will | 830 | * If there is time left scsi_eh_done got called, and we will examine |
817 | * examine the actual status codes to see whether the command | 831 | * the actual status codes to see whether the command actually did |
818 | * actually did complete normally, else tell the host to forget | 832 | * complete normally, else if we have a zero return and no time left, |
819 | * about this command. | 833 | * the command must still be pending, so abort it and return FAILED. |
834 | * If we never actually managed to issue the command, because | ||
835 | * ->queuecommand() kept returning non zero, use the rtn = FAILED | ||
836 | * value above (so don't execute either branch of the if) | ||
820 | */ | 837 | */ |
821 | if (timeleft) { | 838 | if (timeleft) { |
822 | rtn = scsi_eh_completed_normally(scmd); | 839 | rtn = scsi_eh_completed_normally(scmd); |
@@ -837,7 +854,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
837 | rtn = FAILED; | 854 | rtn = FAILED; |
838 | break; | 855 | break; |
839 | } | 856 | } |
840 | } else { | 857 | } else if (!rtn) { |
841 | scsi_abort_eh_cmnd(scmd); | 858 | scsi_abort_eh_cmnd(scmd); |
842 | rtn = FAILED; | 859 | rtn = FAILED; |
843 | } | 860 | } |