Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3233ac19 authored by James Bottomley's avatar James Bottomley
Browse files

[SCSI] sd: retry read_capacity on UNIT_ATTENTION



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: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 14695853
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -1433,6 +1433,8 @@ 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)
{
@@ -1440,7 +1442,7 @@ static int read_capacity_16(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;
	unsigned int alignment;
	unsigned long long lba;
	unsigned sector_size;
@@ -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--;

@@ -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;

@@ -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);