Skip to content

Commit

Permalink
scsi: core: ata: Do no try to probe for CDL on old drives
Browse files Browse the repository at this point in the history
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 <[email protected]>
Fixes: 6248852 ("scsi: core: Detect support for command duration limits")
Cc: [email protected]
Signed-off-by: Damien Le Moal <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Tested-by: David Gow <[email protected]>
Reviewed-by: Bart Van Assche <[email protected]>
Reviewed-by: Niklas Cassel <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
damien-lemoal authored and martinkpetersen committed Sep 22, 2023
1 parent dae40be commit 2132df1
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 1 deletion.
3 changes: 3 additions & 0 deletions drivers/ata/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions drivers/scsi/scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/scsi_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
Expand Down
3 changes: 3 additions & 0 deletions include/scsi/scsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 2132df1

Please sign in to comment.