diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-07-12 10:45:17 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-09-06 18:21:53 -0400 |
commit | 4451e472627881e3e2240b224f127c99be500f91 (patch) | |
tree | 71dfcf330e5dc1faec9c7a54b235d700fc9df68d /drivers | |
parent | e47373ec1c9aab9ee134f4e2b8249957e9f4c7ef (diff) |
[SCSI] sd: pause in sd_spinup_disk for slow USB devices
This patch adds a delay tailored for USB flash devices that are slow to
initialize their firmware. The symptom is a repeated Unit Attention with
ASC=0x28 (Not Ready to Ready transition). The patch will wait for up to 5
seconds for such devices to become ready. Normal devices won't send the
repeated Unit Attention sense key and hence won't trigger the patch.
This fixes a problem with James Roberts-Thomson's USB device, and I've
seen several reports of other devices exhibiting the same symptoms --
presumably they will be helped as well.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/sd.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 0410e1bf109a..41ba0809f791 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -984,7 +984,7 @@ static void | |||
984 | sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, | 984 | sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, |
985 | struct scsi_request *SRpnt, unsigned char *buffer) { | 985 | struct scsi_request *SRpnt, unsigned char *buffer) { |
986 | unsigned char cmd[10]; | 986 | unsigned char cmd[10]; |
987 | unsigned long spintime_value = 0; | 987 | unsigned long spintime_expire = 0; |
988 | int retries, spintime; | 988 | int retries, spintime; |
989 | unsigned int the_result; | 989 | unsigned int the_result; |
990 | struct scsi_sense_hdr sshdr; | 990 | struct scsi_sense_hdr sshdr; |
@@ -1071,12 +1071,27 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, | |||
1071 | scsi_wait_req(SRpnt, (void *)cmd, | 1071 | scsi_wait_req(SRpnt, (void *)cmd, |
1072 | (void *) buffer, 0/*512*/, | 1072 | (void *) buffer, 0/*512*/, |
1073 | SD_TIMEOUT, SD_MAX_RETRIES); | 1073 | SD_TIMEOUT, SD_MAX_RETRIES); |
1074 | spintime_value = jiffies; | 1074 | spintime_expire = jiffies + 100 * HZ; |
1075 | spintime = 1; | ||
1075 | } | 1076 | } |
1076 | spintime = 1; | ||
1077 | /* Wait 1 second for next try */ | 1077 | /* Wait 1 second for next try */ |
1078 | msleep(1000); | 1078 | msleep(1000); |
1079 | printk("."); | 1079 | printk("."); |
1080 | |||
1081 | /* | ||
1082 | * Wait for USB flash devices with slow firmware. | ||
1083 | * Yes, this sense key/ASC combination shouldn't | ||
1084 | * occur here. It's characteristic of these devices. | ||
1085 | */ | ||
1086 | } else if (sense_valid && | ||
1087 | sshdr.sense_key == UNIT_ATTENTION && | ||
1088 | sshdr.asc == 0x28) { | ||
1089 | if (!spintime) { | ||
1090 | spintime_expire = jiffies + 5 * HZ; | ||
1091 | spintime = 1; | ||
1092 | } | ||
1093 | /* Wait 1 second for next try */ | ||
1094 | msleep(1000); | ||
1080 | } else { | 1095 | } else { |
1081 | /* we don't understand the sense code, so it's | 1096 | /* we don't understand the sense code, so it's |
1082 | * probably pointless to loop */ | 1097 | * probably pointless to loop */ |
@@ -1088,8 +1103,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, | |||
1088 | break; | 1103 | break; |
1089 | } | 1104 | } |
1090 | 1105 | ||
1091 | } while (spintime && | 1106 | } while (spintime && time_before_eq(jiffies, spintime_expire)); |
1092 | time_after(spintime_value + 100 * HZ, jiffies)); | ||
1093 | 1107 | ||
1094 | if (spintime) { | 1108 | if (spintime) { |
1095 | if (scsi_status_is_good(the_result)) | 1109 | if (scsi_status_is_good(the_result)) |