[SCSI] Merge scsi-misc-2.6 into scsi-rc-fixes-2.6
[safe/jmp/linux-2.6] / drivers / scsi / sd.c
index de6c603..829cc37 100644 (file)
@@ -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))