Skip to content

Commit

Permalink
[SCSI] sd: retry read_capacity on UNIT_ATTENTION
Browse files Browse the repository at this point in the history
Hazard testing uncovered yet another bug in sd. Under heavy reset
activity the retry counter might be exhausted and the command will be
returned with sense UNIT_ATTENTION/0x29/00 (POWER ON, RESET, OR BUS
DEVICE RESET OCCURRED). In those cases we should just increase the
retry counter again, retrying one more to clear up this Unit Attention
state.

[jejb: update to work with RC16 devices and not to loop endlessly]
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
James Bottomley authored and James Bottomley committed Apr 11, 2010
1 parent 1469585 commit 3233ac1
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1433,14 +1433,16 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
#error RC16_LEN must not be more than SD_BUF_SIZE
#endif

#define READ_CAPACITY_RETRIES_ON_RESET 10

static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
unsigned char *buffer)
{
unsigned char cmd[16];
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int the_result;
int retries = 3;
int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET;
unsigned int alignment;
unsigned long long lba;
unsigned sector_size;
Expand Down Expand Up @@ -1469,6 +1471,13 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
* Invalid Field in CDB, just retry
* silently with RC10 */
return -EINVAL;
if (sense_valid &&
sshdr.sense_key == UNIT_ATTENTION &&
sshdr.asc == 0x29 && sshdr.ascq == 0x00)
/* Device reset might occur several times,
* give it one more chance */
if (--reset_retries > 0)
continue;
}
retries--;

Expand Down Expand Up @@ -1527,7 +1536,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int the_result;
int retries = 3;
int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET;
sector_t lba;
unsigned sector_size;

Expand All @@ -1543,8 +1552,16 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
if (media_not_present(sdkp, &sshdr))
return -ENODEV;

if (the_result)
if (the_result) {
sense_valid = scsi_sense_valid(&sshdr);
if (sense_valid &&
sshdr.sense_key == UNIT_ATTENTION &&
sshdr.asc == 0x29 && sshdr.ascq == 0x00)
/* Device reset might occur several times,
* give it one more chance */
if (--reset_retries > 0)
continue;
}
retries--;

} while (the_result && retries);
Expand Down

0 comments on commit 3233ac1

Please sign in to comment.