diff options
Diffstat (limited to 'drivers/scsi/sd.c')
| -rw-r--r-- | drivers/scsi/sd.c | 25 | 
1 files changed, 22 insertions, 3 deletions
| diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index de6c60320f6..829cc37abc4 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1434,6 +1434,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)  { @@ -1441,7 +1443,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; @@ -1470,6 +1472,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--; @@ -1528,7 +1537,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; @@ -1544,8 +1553,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); @@ -1574,6 +1591,8 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,  static int sd_try_rc16_first(struct scsi_device *sdp)  { +	if (sdp->host->max_cmd_len < 16) +		return 0;  	if (sdp->scsi_level > SCSI_SPC_2)  		return 1;  	if (scsi_device_protection(sdp)) | 
