[PATCH RESEND v4 3/4] ata: libata-scsi: generate SAT sense data for ATA PASS-THROUGH(32)
From: shao.mingyin
Date: Fri Nov 13 2026 - 15:28:04 EST
From: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
ata_scsi_qc_complete() only recognizes ATA PASS-THROUGH(12) and (16).
The 32-byte form takes the ordinary completion path, so CK_COND is
ignored and errors lack the ATA Status Return descriptor. Successful
commands with CK_COND set therefore complete GOOD instead of returning
CHECK CONDITION with the ATA register values.
Recognize ATA PASS-THROUGH(32) by its service action and read CK_COND
from byte 11 instead of byte 2, which belongs to the variable-length
CDB header.
Fixes: b1ffbf854e08 ("libata: Support for an ATA PASS-THROUGH(32) command.")
Cc: stable@xxxxxxxxxxxxxxx
Reviewed-by: Damien Le Moal <dlemoal@xxxxxxxxxx>
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
Changes in v4:
- Code and commit message unchanged; retain Damien Le Moal's Reviewed-by tag.
Previous version: https://lore.kernel.org/all/20261112220122679csrHZJU28_17KSmt_fom7@xxxxxxxxxx/
Changes in v3:
- Code unchanged; retain the Damien Le Moal Reviewed-by tag.
Previous version: https://lore.kernel.org/all/202611112231319337i08AK7ZzIXm9DYFhmtXx@xxxxxxxxxx/
Changes in v2 (Niklas Cassel):
- Move the unrelated invalid-PROTOCOL hunk to patch 1; this patch only
changes the completion path.
- Regenerate with git format-patch so the index matches the diff.
- Keep the Reviewed-by tag; apart from the moved hunk this patch is
unchanged from v1.
v1: https://lore.kernel.org/all/202611042211545962bhKeo8yjWPGFgya4g6LG@xxxxxxxxxx/
Validation on x86-64 with GCC 13 and UBSAN: a userspace harness compiled
ata_scsi_qc_complete() verbatim with sense/completion stubs. For ATA_32,
CK_COND in byte 11 now selected pass-through sense and CHECK CONDITION;
CK_COND clear remained GOOD. Error and preexisting-sense paths selected
the pass-through helpers, and byte 2 did not act as CK_COND. The short
CDB paths and unsupported service-action control were also checked.
drivers/ata/libata-scsi.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index e2847fb32e78b93fd0c8fd3b57e78ae3b17654b6..374918eae53ef4cb082bccd903773f06e6c55fa1 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1888,9 +1888,12 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
struct ata_link *link = qc->dev->link;
struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd;
+ u16 cdb_offset = cdb[0] == VARIABLE_LENGTH_CMD ? 9 : 0;
bool have_sense = qc->flags & ATA_QCFLAG_SENSE_VALID;
- bool is_ata_passthru = cdb[0] == ATA_16 || cdb[0] == ATA_12;
- bool is_ck_cond_request = cdb[2] & 0x20;
+ bool is_ata_passthru = cdb[0] == ATA_16 || cdb[0] == ATA_12 ||
+ (cdb[0] == VARIABLE_LENGTH_CMD &&
+ get_unaligned_be16(&cdb[8]) == ATA_32);
+ bool is_ck_cond_request = cdb[2 + cdb_offset] & 0x20;
bool is_error = qc->err_mask != 0;
/* For ATA pass thru (SAT) commands, generate a sense block if
--
2.27.0