]> git.ipfire.org Git - thirdparty/linux.git/blobdiff - drivers/scsi/scsi_scan.c
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[thirdparty/linux.git] / drivers / scsi / scsi_scan.c
index 9969f4e2f1c3d9c656076e3e540bd17c8352c2af..8d06475de17a33a26921a1ff70c57f759986973f 100644 (file)
@@ -412,7 +412,7 @@ static void scsi_target_dev_release(struct device *dev)
        put_device(parent);
 }
 
-static struct device_type scsi_target_type = {
+static const struct device_type scsi_target_type = {
        .name =         "scsi_target",
        .release =      scsi_target_dev_release,
 };
@@ -626,6 +626,7 @@ void scsi_sanitize_inquiry_string(unsigned char *s, int len)
 }
 EXPORT_SYMBOL(scsi_sanitize_inquiry_string);
 
+
 /**
  * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
  * @sdev:      scsi_device to probe
@@ -647,10 +648,36 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
        int first_inquiry_len, try_inquiry_len, next_inquiry_len;
        int response_len = 0;
        int pass, count, result, resid;
-       struct scsi_sense_hdr sshdr;
+       struct scsi_failure failure_defs[] = {
+               /*
+                * not-ready to ready transition [asc/ascq=0x28/0x0] or
+                * power-on, reset [asc/ascq=0x29/0x0], continue. INQUIRY
+                * should not yield UNIT_ATTENTION but many buggy devices do
+                * so anyway.
+                */
+               {
+                       .sense = UNIT_ATTENTION,
+                       .asc = 0x28,
+                       .result = SAM_STAT_CHECK_CONDITION,
+               },
+               {
+                       .sense = UNIT_ATTENTION,
+                       .asc = 0x29,
+                       .result = SAM_STAT_CHECK_CONDITION,
+               },
+               {
+                       .allowed = 1,
+                       .result = DID_TIME_OUT << 16,
+               },
+               {}
+       };
+       struct scsi_failures failures = {
+               .total_allowed = 3,
+               .failure_definitions = failure_defs,
+       };
        const struct scsi_exec_args exec_args = {
-               .sshdr = &sshdr,
                .resid = &resid,
+               .failures = &failures,
        };
 
        *bflags = 0;
@@ -668,6 +695,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
                                pass, try_inquiry_len));
 
        /* Each pass gets up to three chances to ignore Unit Attention */
+       scsi_failures_reset_retries(&failures);
+
        for (count = 0; count < 3; ++count) {
                memset(scsi_cmd, 0, 6);
                scsi_cmd[0] = INQUIRY;
@@ -684,22 +713,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
                                "scsi scan: INQUIRY %s with code 0x%x\n",
                                result ? "failed" : "successful", result));
 
-               if (result > 0) {
-                       /*
-                        * not-ready to ready transition [asc/ascq=0x28/0x0]
-                        * or power-on, reset [asc/ascq=0x29/0x0], continue.
-                        * INQUIRY should not yield UNIT_ATTENTION
-                        * but many buggy devices do so anyway. 
-                        */
-                       if (scsi_status_is_check_condition(result) &&
-                           scsi_sense_valid(&sshdr)) {
-                               if ((sshdr.sense_key == UNIT_ATTENTION) &&
-                                   ((sshdr.asc == 0x28) ||
-                                    (sshdr.asc == 0x29)) &&
-                                   (sshdr.ascq == 0))
-                                       continue;
-                       }
-               } else if (result == 0) {
+               if (result == 0) {
                        /*
                         * if nothing was transferred, we try
                         * again. It's a workaround for some USB
@@ -1402,14 +1416,34 @@ static int scsi_report_lun_scan(struct scsi_target *starget, blist_flags_t bflag
        unsigned int length;
        u64 lun;
        unsigned int num_luns;
-       unsigned int retries;
        int result;
        struct scsi_lun *lunp, *lun_data;
-       struct scsi_sense_hdr sshdr;
        struct scsi_device *sdev;
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+       struct scsi_failure failure_defs[] = {
+               {
+                       .sense = UNIT_ATTENTION,
+                       .asc = SCMD_FAILURE_ASC_ANY,
+                       .ascq = SCMD_FAILURE_ASCQ_ANY,
+                       .result = SAM_STAT_CHECK_CONDITION,
+               },
+               /* Fail all CCs except the UA above */
+               {
+                       .sense = SCMD_FAILURE_SENSE_ANY,
+                       .result = SAM_STAT_CHECK_CONDITION,
+               },
+               /* Retry any other errors not listed above */
+               {
+                       .result = SCMD_FAILURE_RESULT_ANY,
+               },
+               {}
+       };
+       struct scsi_failures failures = {
+               .total_allowed = 3,
+               .failure_definitions = failure_defs,
+       };
        const struct scsi_exec_args exec_args = {
-               .sshdr = &sshdr,
+               .failures = &failures,
        };
        int ret = 0;
 
@@ -1480,29 +1514,18 @@ retry:
         * should come through as a check condition, and will not generate
         * a retry.
         */
-       for (retries = 0; retries < 3; retries++) {
-               SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
-                               "scsi scan: Sending REPORT LUNS to (try %d)\n",
-                               retries));
-
-               result = scsi_execute_cmd(sdev, scsi_cmd, REQ_OP_DRV_IN,
-                                         lun_data, length,
-                                         SCSI_REPORT_LUNS_TIMEOUT, 3,
-                                         &exec_args);
+       scsi_failures_reset_retries(&failures);
 
-               SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
-                               "scsi scan: REPORT LUNS"
-                               " %s (try %d) result 0x%x\n",
-                               result ?  "failed" : "successful",
-                               retries, result));
-               if (result == 0)
-                       break;
-               else if (scsi_sense_valid(&sshdr)) {
-                       if (sshdr.sense_key != UNIT_ATTENTION)
-                               break;
-               }
-       }
+       SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
+                         "scsi scan: Sending REPORT LUNS\n"));
 
+       result = scsi_execute_cmd(sdev, scsi_cmd, REQ_OP_DRV_IN, lun_data,
+                                 length, SCSI_REPORT_LUNS_TIMEOUT, 3,
+                                 &exec_args);
+
+       SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
+                         "scsi scan: REPORT LUNS  %s result 0x%x\n",
+                         result ?  "failed" : "successful", result));
        if (result) {
                /*
                 * The device probably does not support a REPORT LUN command