scsi: core: ata: Do no try to probe for CDL on old drives
authorDamien Le Moal <dlemoal@kernel.org>
Fri, 15 Sep 2023 02:20:34 +0000 (11:20 +0900)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 22 Sep 2023 01:07:23 +0000 (21:07 -0400)
Some old drives (e.g. an Ultra320 SCSI disk as reported by John) do not
seem to execute MAINTENANCE_IN / MI_REPORT_SUPPORTED_OPERATION_CODES
commands correctly and hang when a non-zero service action is specified
(one command format with service action case in scsi_report_opcode()).

Currently, CDL probing with scsi_cdl_check_cmd() is the only caller using a
non zero service action for scsi_report_opcode(). To avoid issues with
these old drives, do not attempt CDL probe if the device reports support
for an SPC version lower than 5 (CDL was introduced in SPC-5). To keep
things working with ATA devices which probe for the CDL T2A and T2B pages
introduced with SPC-6, modify ata_scsiop_inq_std() to claim SPC-6 version
compatibility for ATA drives supporting CDL.

SPC-6 standard version number is defined as Dh (= 13) in SPC-6 r09. Fix
scsi_probe_lun() to correctly capture this value by changing the bit mask
for the second byte of the INQUIRY response from 0x7 to 0xf.
include/scsi/scsi.h is modified to add the definition SCSI_SPC_6 with the
value 14 (Dh + 1). The missing definitions for the SCSI_SPC_4 and
SCSI_SPC_5 versions are also added.

Reported-by: John David Anglin <dave.anglin@bell.net>
Fixes: 624885209f31 ("scsi: core: Detect support for command duration limits")
Cc: stable@vger.kernel.org
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://lore.kernel.org/r/20230915022034.678121-1-dlemoal@kernel.org
Tested-by: David Gow <david@davidgow.net>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/ata/libata-scsi.c
drivers/scsi/scsi.c
drivers/scsi/scsi_scan.c
include/scsi/scsi.h

index d3f28b8..0e96ed4 100644 (file)
@@ -1835,6 +1835,9 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
                hdr[2] = 0x7; /* claim SPC-5 version compatibility */
        }
 
+       if (args->dev->flags & ATA_DFLAG_CDL)
+               hdr[2] = 0xd; /* claim SPC-6 version compatibility */
+
        memcpy(rbuf, hdr, sizeof(hdr));
        memcpy(&rbuf[8], "ATA     ", 8);
        ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
index d0911bc..89367c4 100644 (file)
@@ -613,6 +613,17 @@ void scsi_cdl_check(struct scsi_device *sdev)
        bool cdl_supported;
        unsigned char *buf;
 
+       /*
+        * Support for CDL was defined in SPC-5. Ignore devices reporting an
+        * lower SPC version. This also avoids problems with old drives choking
+        * on MAINTENANCE_IN / MI_REPORT_SUPPORTED_OPERATION_CODES with a
+        * service action specified, as done in scsi_cdl_check_cmd().
+        */
+       if (sdev->scsi_level < SCSI_SPC_5) {
+               sdev->cdl_supported = 0;
+               return;
+       }
+
        buf = kmalloc(SCSI_CDL_CHECK_BUF_LEN, GFP_KERNEL);
        if (!buf) {
                sdev->cdl_supported = 0;
index 52014b2..eaa972b 100644 (file)
@@ -822,7 +822,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
         * device is attached at LUN 0 (SCSI_SCAN_TARGET_PRESENT) so
         * non-zero LUNs can be scanned.
         */
-       sdev->scsi_level = inq_result[2] & 0x07;
+       sdev->scsi_level = inq_result[2] & 0x0f;
        if (sdev->scsi_level >= 2 ||
            (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1))
                sdev->scsi_level++;
index ec09359..4498f84 100644 (file)
@@ -157,6 +157,9 @@ enum scsi_disposition {
 #define SCSI_3          4        /* SPC */
 #define SCSI_SPC_2      5
 #define SCSI_SPC_3      6
+#define SCSI_SPC_4     7
+#define SCSI_SPC_5     8
+#define SCSI_SPC_6     14
 
 /*
  * INQ PERIPHERAL QUALIFIERS