--- /dev/null
+From stable+bounces-227631-greg=kroah.com@vger.kernel.org Fri Mar 20 22:55:12 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 17:54:45 -0400
+Subject: ata: libata-scsi: report correct sense field pointer in ata_scsiop_maint_in()
+To: stable@vger.kernel.org
+Cc: Damien Le Moal <dlemoal@kernel.org>, Guenter Roeck <linux@roeck-us.net>, Niklas Cassel <cassel@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260320215445.132838-2-sashal@kernel.org>
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit e6d7eba23b666d85cacee0643be280d6ce1ebffc ]
+
+Commit 4ab7bb976343 ("ata: libata-scsi: Refactor ata_scsiop_maint_in()")
+modified ata_scsiop_maint_in() to directly call
+ata_scsi_set_invalid_field() to set the field pointer of the sense data
+of a failed MAINTENANCE IN command. However, in the case of an invalid
+command format, the sense data field incorrectly indicates byte 1 of
+the CDB. Fix this to indicate byte 2 of the command.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: 4ab7bb976343 ("ata: libata-scsi: Refactor ata_scsiop_maint_in()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ata/libata-scsi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -3611,7 +3611,7 @@ static unsigned int ata_scsiop_maint_in(
+
+ if (cdb[2] != 1 && cdb[2] != 3) {
+ ata_dev_warn(dev, "invalid command format %d\n", cdb[2]);
+- ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
++ ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
+ return 0;
+ }
+
--- /dev/null
+From stable+bounces-227630-greg=kroah.com@vger.kernel.org Fri Mar 20 22:55:07 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 17:54:44 -0400
+Subject: ata: libata-scsi: Return residual for emulated SCSI commands
+To: stable@vger.kernel.org
+Cc: Damien Le Moal <dlemoal@kernel.org>, Niklas Cassel <cassel@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260320215445.132838-1-sashal@kernel.org>
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit 5251ae224d8d3caa21b28d12408062b6e75cffad ]
+
+The function ata_scsi_rbuf_fill() used to fill the reply buffer of
+emulated SCSI commands always copies the ATA reply buffer
+(ata_scsi_rbuf) up to the size of the SCSI command buffer (the transfer
+length for the command), even if the reply is shorter than the SCSI
+command buffer. This leads to issuers of the SCSI command to always get
+a result without any residual (resid is always 0) despite the
+potentially shorter reply for the command.
+
+Modify all fill actors used by ata_scsi_rbuf_fill() to return the number
+of bytes filled for the reply and 0 in case of error. Using this value,
+add a call to scsi_set_resid() in ata_scsi_rbuf_fill() to set the
+correct residual for the SCSI command when the reply length is shorter
+than the command buffer.
+
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Link: https://lore.kernel.org/r/20241022024537.251905-7-dlemoal@kernel.org
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Stable-dep-of: e6d7eba23b66 ("ata: libata-scsi: report correct sense field pointer in ata_scsiop_maint_in()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ata/libata-scsi.c | 81 ++++++++++++++++++++++++++--------------------
+ 1 file changed, 47 insertions(+), 34 deletions(-)
+
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -1920,17 +1920,19 @@ static void ata_scsi_rbuf_fill(struct at
+ unsigned int (*actor)(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf))
+ {
+- unsigned int rc;
+ unsigned long flags;
++ unsigned int len;
+
+ spin_lock_irqsave(&ata_scsi_rbuf_lock, flags);
+
+ memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
+- rc = actor(dev, cmd, ata_scsi_rbuf);
+- if (rc == 0) {
++ len = actor(dev, cmd, ata_scsi_rbuf);
++ if (len) {
+ sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
+ ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
+ cmd->result = SAM_STAT_GOOD;
++ if (scsi_bufflen(cmd) > len)
++ scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
+ }
+
+ spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags);
+@@ -2018,7 +2020,11 @@ static unsigned int ata_scsiop_inq_std(s
+ else
+ memcpy(rbuf + 58, versions, sizeof(versions));
+
+- return 0;
++ /*
++ * Include all 8 possible version descriptors, even if not all of
++ * them are popoulated.
++ */
++ return 96;
+ }
+
+ /**
+@@ -2055,7 +2061,8 @@ static unsigned int ata_scsiop_inq_00(st
+ num_pages++;
+ }
+ rbuf[3] = num_pages; /* number of supported VPD pages */
+- return 0;
++
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2082,7 +2089,8 @@ static unsigned int ata_scsiop_inq_80(st
+ memcpy(rbuf, hdr, sizeof(hdr));
+ ata_id_string(dev->id, (unsigned char *) &rbuf[4],
+ ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+- return 0;
++
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2143,7 +2151,8 @@ static unsigned int ata_scsiop_inq_83(st
+ num += ATA_ID_WWN_LEN;
+ }
+ rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */
+- return 0;
++
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2180,7 +2189,8 @@ static unsigned int ata_scsiop_inq_89(st
+ rbuf[56] = ATA_CMD_ID_ATA;
+
+ memcpy(&rbuf[60], &dev->id[0], 512);
+- return 0;
++
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2231,7 +2241,7 @@ static unsigned int ata_scsiop_inq_b0(st
+ put_unaligned_be32(1, &rbuf[28]);
+ }
+
+- return 0;
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2261,7 +2271,7 @@ static unsigned int ata_scsiop_inq_b1(st
+ if (zoned)
+ rbuf[8] = (zoned << 4);
+
+- return 0;
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2284,7 +2294,7 @@ static unsigned int ata_scsiop_inq_b2(st
+ rbuf[3] = 0x4;
+ rbuf[5] = 1 << 6; /* TPWS */
+
+- return 0;
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2304,7 +2314,7 @@ static unsigned int ata_scsiop_inq_b6(st
+ {
+ if (!ata_dev_is_zac(dev)) {
+ ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
+- return 1;
++ return 0;
+ }
+
+ /*
+@@ -2322,7 +2332,7 @@ static unsigned int ata_scsiop_inq_b6(st
+ put_unaligned_be32(dev->zac_zones_optimal_nonseq, &rbuf[12]);
+ put_unaligned_be32(dev->zac_zones_max_open, &rbuf[16]);
+
+- return 0;
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2346,7 +2356,7 @@ static unsigned int ata_scsiop_inq_b9(st
+
+ if (!cpr_log) {
+ ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
+- return 1;
++ return 0;
+ }
+
+ /* SCSI Concurrent Positioning Ranges VPD page: SBC-5 rev 1 or later */
+@@ -2360,7 +2370,7 @@ static unsigned int ata_scsiop_inq_b9(st
+ put_unaligned_be64(cpr_log->cpr[i].num_lbas, &desc[16]);
+ }
+
+- return 0;
++ return get_unaligned_be16(&rbuf[2]) + 4;
+ }
+
+ /**
+@@ -2382,7 +2392,7 @@ static unsigned int ata_scsiop_inquiry(s
+ /* is CmdDt set? */
+ if (scsicmd[1] & 2) {
+ ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+- return 1;
++ return 0;
+ }
+
+ /* Is EVPD clear? */
+@@ -2410,7 +2420,7 @@ static unsigned int ata_scsiop_inquiry(s
+ return ata_scsiop_inq_b9(dev, cmd, rbuf);
+ default:
+ ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
+- return 1;
++ return 0;
+ }
+ }
+
+@@ -2741,24 +2751,27 @@ static unsigned int ata_scsiop_mode_sens
+ rbuf[3] = sizeof(sat_blk_desc);
+ memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
+ }
+- } else {
+- put_unaligned_be16(p - rbuf - 2, &rbuf[0]);
+- rbuf[3] |= dpofua;
+- if (ebd) {
+- rbuf[7] = sizeof(sat_blk_desc);
+- memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
+- }
++
++ return rbuf[0] + 1;
+ }
+- return 0;
++
++ put_unaligned_be16(p - rbuf - 2, &rbuf[0]);
++ rbuf[3] |= dpofua;
++ if (ebd) {
++ rbuf[7] = sizeof(sat_blk_desc);
++ memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
++ }
++
++ return get_unaligned_be16(&rbuf[0]) + 2;
+
+ invalid_fld:
+ ata_scsi_set_invalid_field(dev, cmd, fp, bp);
+- return 1;
++ return 0;
+
+ saving_not_supp:
+ ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x39, 0x0);
+ /* "Saving parameters not supported" */
+- return 1;
++ return 0;
+ }
+
+ /**
+@@ -2801,7 +2814,7 @@ static unsigned int ata_scsiop_read_cap(
+ rbuf[6] = sector_size >> (8 * 1);
+ rbuf[7] = sector_size;
+
+- return 0;
++ return 8;
+ }
+
+ /*
+@@ -2811,7 +2824,7 @@ static unsigned int ata_scsiop_read_cap(
+ if (scsicmd[0] != SERVICE_ACTION_IN_16 ||
+ (scsicmd[1] & 0x1f) != SAI_READ_CAPACITY_16) {
+ ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+- return 1;
++ return 0;
+ }
+
+ /* sector count, 64-bit */
+@@ -2846,7 +2859,7 @@ static unsigned int ata_scsiop_read_cap(
+ }
+ }
+
+- return 0;
++ return 16;
+ }
+
+ /**
+@@ -2865,7 +2878,7 @@ static unsigned int ata_scsiop_report_lu
+ {
+ rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */
+
+- return 0;
++ return 16;
+ }
+
+ /*
+@@ -3593,13 +3606,13 @@ static unsigned int ata_scsiop_maint_in(
+
+ if ((cdb[1] & 0x1f) != MI_REPORT_SUPPORTED_OPERATION_CODES) {
+ ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+- return 1;
++ return 0;
+ }
+
+ if (cdb[2] != 1 && cdb[2] != 3) {
+ ata_dev_warn(dev, "invalid command format %d\n", cdb[2]);
+ ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+- return 1;
++ return 0;
+ }
+
+ switch (cdb[3]) {
+@@ -3672,7 +3685,7 @@ static unsigned int ata_scsiop_maint_in(
+ rbuf[0] = rwcdlp;
+ rbuf[1] = cdlp | supported;
+
+- return 0;
++ return 4;
+ }
+
+ /**