[PATCH v2] ata: libata-scsi: abort multi-sector pass-through commands when multi_count is 0
From: Hui Peng
Date: Sun Sep 20 2026 - 23:26:06 EST
When an ATA_12, ATA_16, or ATA_32 pass-through command with a
multi-sector PIO command opcode (ATA_CMD_READ_MULTI,
ATA_CMD_WRITE_MULTI, ATA_CMD_READ_MULTI_EXT, ATA_CMD_WRITE_MULTI_EXT, or
ATA_CMD_WRITE_MULTI_FUA_EXT) is submitted via SG_IO on a device where
multiple-sector mode is not configured (dev->multi_count == 0),
ata_scsi_pass_thru() currently logs a warning and still dispatches the
taskfile. When the DRQ interrupt fires, ata_pio_sectors() triggers
WARN_ON_ONCE(qc->dev->multi_count == 0) and computes
nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size, 0) = 0, failing
to transfer any sectors:
ata1.00: invalid multi_count 1 ignored
WARNING: drivers/ata/libata-sff.c:666 at ata_pio_sectors+0x27d/0x300
Call Trace:
<IRQ>
ata_sff_hsm_move+0x211/0x22e0
__ata_sff_port_intr+0x1c8/0x520
ata_bmdma_port_intr+0xa1/0x5b0
ata_bmdma_interrupt+0x1f5/0x550
Per ACS-3 section 7.12.7.21, if IDENTIFY DEVICE word 59 bit 8 is cleared
to zero (multi_count == 0) and a READ MULTIPLE or WRITE MULTIPLE command
is received without a preceding successful SET MULTIPLE MODE command, the
device returns command aborted (ABRT). Per the SAT specification, an ABRT
error translates to the ABORTED COMMAND sense key with NO ADDITIONAL SENSE
INFORMATION (0x00, 0x00).
Fail multi-sector taskfile commands in ata_scsi_pass_thru() with
ata_scsi_set_sense(dev, scmd, ABORTED_COMMAND, 0, 0) when
dev->multi_count == 0.
Tested in QEMU against Linux 7.3.0-rc3 (-device ide-cf, where
dev->multi_count is 0) by issuing ATA_CMD_SET_MULTI (nsect=1) followed
by an SG_IO ATA_16 ATA_CMD_READ_MULTI command: on the unfixed kernel
this triggers WARNING: drivers/ata/libata-sff.c:666 in
ata_pio_sectors(), whereas on the fixed kernel it immediately completes
with sense key ABORTED_COMMAND (0x0b, 0x00, 0x00) and 0 warnings.
Fixes: 1dce589c38c3 ("libata passthru: support PIO multi commands")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@xxxxxxxxx>
---
Changes in v2:
- Report sense key ABORTED_COMMAND (0x00, 0x00) via ata_scsi_set_sense()
per ACS-3 and SAT specifications instead of ILLEGAL_REQUEST /
invalid_fld, as pointed out by Damien Le Moal.
- Update the commit description to accurately describe the
ata_pio_sectors() WARN_ON_ONCE(qc->dev->multi_count == 0) and 0-sector
transfer path and fix the Fixes: tag to 1dce589c38c3.
drivers/ata/libata-scsi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b3666519b648..29fd6d8d97ce 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3507,6 +3507,11 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
if (is_multi_taskfile(tf)) {
unsigned int multi_count = 1 << (cdb[1] >> 5);
+ if (!dev->multi_count) {
+ ata_scsi_set_sense(dev, scmd, ABORTED_COMMAND, 0, 0);
+ return 1;
+ }
+
/* compare the passed through multi_count
* with the cached multi_count of libata
*/
--
2.49.0