Commit b1189068 authored by Niklas Cassel's avatar Niklas Cassel
Browse files

ata: libata-scsi: Fix system suspend for a security locked drive



Commit cf3fc037 ("ata: libata-scsi: Fix ata_to_sense_error() status
handling") fixed ata_to_sense_error() to properly generate sense key
ABORTED COMMAND (without any additional sense code), instead of the
previous bogus sense key ILLEGAL REQUEST with the additional sense code
UNALIGNED WRITE COMMAND, for a failed command.

However, this broke suspend for Security locked drives (drives that have
Security enabled, and have not been Security unlocked by boot firmware).

The reason for this is that the SCSI disk driver, for the Synchronize
Cache command only, treats any sense data with sense key ILLEGAL REQUEST
as a successful command (regardless of ASC / ASCQ).

After commit cf3fc037 ("ata: libata-scsi: Fix ata_to_sense_error()
status handling") the code that treats any sense data with sense key
ILLEGAL REQUEST as a successful command is no longer applicable, so the
command fails, which causes the system suspend to be aborted:

  sd 1:0:0:0: PM: dpm_run_callback(): scsi_bus_suspend returns -5
  sd 1:0:0:0: PM: failed to suspend async: error -5
  PM: Some devices failed to suspend, or early wake event detected

To make suspend work once again, for a Security locked device only,
return sense data LOGICAL UNIT ACCESS NOT AUTHORIZED, the actual sense
data which a real SCSI device would have returned if locked.
The SCSI disk driver treats this sense data as a successful command.

Cc: stable@vger.kernel.org
Reported-by: default avatarIlia Baryshnikov <qwelias@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220704


Fixes: cf3fc037 ("ata: libata-scsi: Fix ata_to_sense_error() status handling")
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: default avatarDamien Le Moal <dlemoal@kernel.org>
Signed-off-by: default avatarNiklas Cassel <cassel@kernel.org>
parent b32cc17d
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -992,6 +992,13 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
		return;
	}

	if (ata_id_is_locked(dev->id)) {
		/* Security locked */
		/* LOGICAL UNIT ACCESS NOT AUTHORIZED */
		ata_scsi_set_sense(dev, cmd, DATA_PROTECT, 0x74, 0x71);
		return;
	}

	if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
		ata_dev_dbg(dev,
			    "Missing result TF: reporting aborted command\n");
+1 −0
Original line number Diff line number Diff line
@@ -566,6 +566,7 @@ struct ata_bmdma_prd {
#define ata_id_has_ncq(id)	((id)[ATA_ID_SATA_CAPABILITY] & (1 << 8))
#define ata_id_queue_depth(id)	(((id)[ATA_ID_QUEUE_DEPTH] & 0x1f) + 1)
#define ata_id_removable(id)	((id)[ATA_ID_CONFIG] & (1 << 7))
#define ata_id_is_locked(id)	(((id)[ATA_ID_DLF] & 0x7) == 0x7)
#define ata_id_has_atapi_AN(id)	\
	((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \
	  ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \