* [PATCH v4 1/8] ata: libata-scsi: Fix offsets for the fixed format sense data
2024-07-01 19:57 [PATCH v4 0/8] ATA PASS-THROUGH sense data fixes Igor Pylypiv
@ 2024-07-01 19:57 ` Igor Pylypiv
2024-07-01 21:09 ` Niklas Cassel
2024-07-01 19:57 ` [PATCH v4 2/8] ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1 Igor Pylypiv
` (6 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-01 19:57 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: Tejun Heo, Hannes Reinecke, linux-ide, linux-kernel, Igor Pylypiv,
Akshat Jain, stable
Correct the ATA PASS-THROUGH fixed format sense data offsets to conform
to SPC-6 and SAT-5 specifications. Additionally, set the VALID bit to
indicate that the INFORMATION field contains valid information.
INFORMATION
===========
SAT-5 Table 212 — "Fixed format sense data INFORMATION field for the ATA
PASS-THROUGH commands" defines the following format:
+------+------------+
| Byte | Field |
+------+------------+
| 0 | ERROR |
| 1 | STATUS |
| 2 | DEVICE |
| 3 | COUNT(7:0) |
+------+------------+
SPC-6 Table 48 - "Fixed format sense data" specifies that the INFORMATION
field starts at byte 3 in sense buffer resulting in the following offsets
for the ATA PASS-THROUGH commands:
+------------+-------------------------+
| Field | Offset in sense buffer |
+------------+-------------------------+
| ERROR | 3 |
| STATUS | 4 |
| DEVICE | 5 |
| COUNT(7:0) | 6 |
+------------+-------------------------+
COMMAND-SPECIFIC INFORMATION
============================
SAT-5 Table 213 - "Fixed format sense data COMMAND-SPECIFIC INFORMATION
field for ATA PASS-THROUGH" defines the following format:
+------+-------------------+
| Byte | Field |
+------+-------------------+
| 0 | FLAGS | LOG INDEX |
| 1 | LBA (7:0) |
| 2 | LBA (15:8) |
| 3 | LBA (23:16) |
+------+-------------------+
SPC-6 Table 48 - "Fixed format sense data" specifies that
the COMMAND-SPECIFIC-INFORMATION field starts at byte 8
in sense buffer resulting in the following offsets for
the ATA PASS-THROUGH commands:
Offsets of these fields in the fixed sense format are as follows:
+-------------------+-------------------------+
| Field | Offset in sense buffer |
+-------------------+-------------------------+
| FLAGS | LOG INDEX | 8 |
| LBA (7:0) | 9 |
| LBA (15:8) | 10 |
| LBA (23:16) | 11 |
+-------------------+-------------------------+
Reported-by: Akshat Jain <akshatzen@google.com>
Fixes: 11093cb1ef56 ("libata-scsi: generate correct ATA pass-through sense")
Cc: stable@vger.kernel.org
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
drivers/ata/libata-scsi.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index bb4d30d377ae..a9e44ad4c2de 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -855,7 +855,6 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->result_tf;
unsigned char *sb = cmd->sense_buffer;
- unsigned char *desc = sb + 8;
u8 sense_key, asc, ascq;
memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
@@ -877,7 +876,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D);
}
- if ((cmd->sense_buffer[0] & 0x7f) >= 0x72) {
+ if ((sb[0] & 0x7f) >= 0x72) {
+ unsigned char *desc;
u8 len;
/* descriptor format */
@@ -916,21 +916,21 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
}
} else {
/* Fixed sense format */
- desc[0] = tf->error;
- desc[1] = tf->status;
- desc[2] = tf->device;
- desc[3] = tf->nsect;
- desc[7] = 0;
+ sb[0] |= 0x80;
+ sb[3] = tf->error;
+ sb[4] = tf->status;
+ sb[5] = tf->device;
+ sb[6] = tf->nsect;
if (tf->flags & ATA_TFLAG_LBA48) {
- desc[8] |= 0x80;
+ sb[8] |= 0x80;
if (tf->hob_nsect)
- desc[8] |= 0x40;
+ sb[8] |= 0x40;
if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
- desc[8] |= 0x20;
+ sb[8] |= 0x20;
}
- desc[9] = tf->lbal;
- desc[10] = tf->lbam;
- desc[11] = tf->lbah;
+ sb[9] = tf->lbal;
+ sb[10] = tf->lbam;
+ sb[11] = tf->lbah;
}
}
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v4 1/8] ata: libata-scsi: Fix offsets for the fixed format sense data
2024-07-01 19:57 ` [PATCH v4 1/8] ata: libata-scsi: Fix offsets for the fixed format sense data Igor Pylypiv
@ 2024-07-01 21:09 ` Niklas Cassel
0 siblings, 0 replies; 18+ messages in thread
From: Niklas Cassel @ 2024-07-01 21:09 UTC (permalink / raw)
To: Igor Pylypiv
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel, Akshat Jain, stable
On Mon, Jul 01, 2024 at 07:57:51PM +0000, Igor Pylypiv wrote:
> Correct the ATA PASS-THROUGH fixed format sense data offsets to conform
> to SPC-6 and SAT-5 specifications. Additionally, set the VALID bit to
> indicate that the INFORMATION field contains valid information.
>
> INFORMATION
> ===========
>
> SAT-5 Table 212 — "Fixed format sense data INFORMATION field for the ATA
> PASS-THROUGH commands" defines the following format:
>
> +------+------------+
> | Byte | Field |
> +------+------------+
> | 0 | ERROR |
> | 1 | STATUS |
> | 2 | DEVICE |
> | 3 | COUNT(7:0) |
> +------+------------+
>
> SPC-6 Table 48 - "Fixed format sense data" specifies that the INFORMATION
> field starts at byte 3 in sense buffer resulting in the following offsets
> for the ATA PASS-THROUGH commands:
>
> +------------+-------------------------+
> | Field | Offset in sense buffer |
> +------------+-------------------------+
> | ERROR | 3 |
> | STATUS | 4 |
> | DEVICE | 5 |
> | COUNT(7:0) | 6 |
> +------------+-------------------------+
>
> COMMAND-SPECIFIC INFORMATION
> ============================
>
> SAT-5 Table 213 - "Fixed format sense data COMMAND-SPECIFIC INFORMATION
> field for ATA PASS-THROUGH" defines the following format:
>
> +------+-------------------+
> | Byte | Field |
> +------+-------------------+
> | 0 | FLAGS | LOG INDEX |
> | 1 | LBA (7:0) |
> | 2 | LBA (15:8) |
> | 3 | LBA (23:16) |
> +------+-------------------+
>
> SPC-6 Table 48 - "Fixed format sense data" specifies that
> the COMMAND-SPECIFIC-INFORMATION field starts at byte 8
> in sense buffer resulting in the following offsets for
> the ATA PASS-THROUGH commands:
>
> Offsets of these fields in the fixed sense format are as follows:
>
> +-------------------+-------------------------+
> | Field | Offset in sense buffer |
> +-------------------+-------------------------+
> | FLAGS | LOG INDEX | 8 |
> | LBA (7:0) | 9 |
> | LBA (15:8) | 10 |
> | LBA (23:16) | 11 |
> +-------------------+-------------------------+
>
> Reported-by: Akshat Jain <akshatzen@google.com>
> Fixes: 11093cb1ef56 ("libata-scsi: generate correct ATA pass-through sense")
> Cc: stable@vger.kernel.org
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> ---
> drivers/ata/libata-scsi.c | 26 +++++++++++++-------------
> 1 file changed, 13 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index bb4d30d377ae..a9e44ad4c2de 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -855,7 +855,6 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> struct scsi_cmnd *cmd = qc->scsicmd;
> struct ata_taskfile *tf = &qc->result_tf;
> unsigned char *sb = cmd->sense_buffer;
> - unsigned char *desc = sb + 8;
> u8 sense_key, asc, ascq;
>
> memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
> @@ -877,7 +876,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D);
> }
>
> - if ((cmd->sense_buffer[0] & 0x7f) >= 0x72) {
> + if ((sb[0] & 0x7f) >= 0x72) {
> + unsigned char *desc;
> u8 len;
>
> /* descriptor format */
> @@ -916,21 +916,21 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> }
> } else {
> /* Fixed sense format */
> - desc[0] = tf->error;
> - desc[1] = tf->status;
> - desc[2] = tf->device;
> - desc[3] = tf->nsect;
> - desc[7] = 0;
> + sb[0] |= 0x80;
> + sb[3] = tf->error;
> + sb[4] = tf->status;
> + sb[5] = tf->device;
> + sb[6] = tf->nsect;
> if (tf->flags & ATA_TFLAG_LBA48) {
> - desc[8] |= 0x80;
> + sb[8] |= 0x80;
> if (tf->hob_nsect)
> - desc[8] |= 0x40;
> + sb[8] |= 0x40;
> if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
> - desc[8] |= 0x20;
> + sb[8] |= 0x20;
> }
> - desc[9] = tf->lbal;
> - desc[10] = tf->lbam;
> - desc[11] = tf->lbah;
> + sb[9] = tf->lbal;
> + sb[10] = tf->lbam;
> + sb[11] = tf->lbah;
> }
> }
>
> --
> 2.45.2.803.g4e1b14247a-goog
>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 2/8] ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1
2024-07-01 19:57 [PATCH v4 0/8] ATA PASS-THROUGH sense data fixes Igor Pylypiv
2024-07-01 19:57 ` [PATCH v4 1/8] ata: libata-scsi: Fix offsets for the fixed format sense data Igor Pylypiv
@ 2024-07-01 19:57 ` Igor Pylypiv
2024-07-01 21:15 ` Niklas Cassel
2024-07-01 19:57 ` [PATCH v4 3/8] ata: libata-scsi: Honour the D_SENSE bit for CK_COND=1 and no error Igor Pylypiv
` (5 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-01 19:57 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: Tejun Heo, Hannes Reinecke, linux-ide, linux-kernel, Igor Pylypiv,
stable
Current ata_gen_passthru_sense() code performs two actions:
1. Generates sense data based on the ATA 'status' and ATA 'error' fields.
2. Populates "ATA Status Return sense data descriptor" / "Fixed format
sense data" with ATA taskfile fields.
The problem is that #1 generates sense data even when a valid sense data
is already present (ATA_QCFLAG_SENSE_VALID is set). Factoring out #2 into
a separate function allows us to generate sense data only when there is
no valid sense data (ATA_QCFLAG_SENSE_VALID is not set).
As a bonus, we can now delete a FIXME comment in atapi_qc_complete()
which states that we don't want to translate taskfile registers into
sense descriptors for ATAPI.
Cc: stable@vger.kernel.org # 4.19+
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
drivers/ata/libata-scsi.c | 158 +++++++++++++++++++++-----------------
1 file changed, 86 insertions(+), 72 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a9e44ad4c2de..26b1263f5c7c 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -230,6 +230,80 @@ void ata_scsi_set_sense_information(struct ata_device *dev,
SCSI_SENSE_BUFFERSIZE, information);
}
+/**
+ * ata_scsi_set_passthru_sense_fields - Set ATA fields in sense buffer
+ * @qc: ATA PASS-THROUGH command.
+ *
+ * Populates "ATA Status Return sense data descriptor" / "Fixed format
+ * sense data" with ATA taskfile fields.
+ *
+ * LOCKING:
+ * None.
+ */
+static void ata_scsi_set_passthru_sense_fields(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ struct ata_taskfile *tf = &qc->result_tf;
+ unsigned char *sb = cmd->sense_buffer;
+
+ if ((sb[0] & 0x7f) >= 0x72) {
+ unsigned char *desc;
+ u8 len;
+
+ /* descriptor format */
+ len = sb[7];
+ desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
+ if (!desc) {
+ if (SCSI_SENSE_BUFFERSIZE < len + 14)
+ return;
+ sb[7] = len + 14;
+ desc = sb + 8 + len;
+ }
+ desc[0] = 9;
+ desc[1] = 12;
+ /*
+ * Copy registers into sense buffer.
+ */
+ desc[2] = 0x00;
+ desc[3] = tf->error;
+ desc[5] = tf->nsect;
+ desc[7] = tf->lbal;
+ desc[9] = tf->lbam;
+ desc[11] = tf->lbah;
+ desc[12] = tf->device;
+ desc[13] = tf->status;
+
+ /*
+ * Fill in Extend bit, and the high order bytes
+ * if applicable.
+ */
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ desc[2] |= 0x01;
+ desc[4] = tf->hob_nsect;
+ desc[6] = tf->hob_lbal;
+ desc[8] = tf->hob_lbam;
+ desc[10] = tf->hob_lbah;
+ }
+ } else {
+ /* Fixed sense format */
+ sb[0] |= 0x80;
+ sb[3] = tf->error;
+ sb[4] = tf->status;
+ sb[5] = tf->device;
+ sb[6] = tf->nsect;
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ sb[8] |= 0x80;
+ if (tf->hob_nsect)
+ sb[8] |= 0x40;
+ if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
+ sb[8] |= 0x20;
+ }
+ sb[9] = tf->lbal;
+ sb[10] = tf->lbam;
+ sb[11] = tf->lbah;
+ }
+}
+
static void ata_scsi_set_invalid_field(struct ata_device *dev,
struct scsi_cmnd *cmd, u16 field, u8 bit)
{
@@ -837,10 +911,8 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
* ata_gen_passthru_sense - Generate check condition sense block.
* @qc: Command that completed.
*
- * This function is specific to the ATA descriptor format sense
- * block specified for the ATA pass through commands. Regardless
- * of whether the command errored or not, return a sense
- * block. Copy all controller registers into the sense
+ * This function is specific to the ATA pass through commands.
+ * Regardless of whether the command errored or not, return a sense
* block. If there was no error, we get the request from an ATA
* passthrough command, so we use the following sense data:
* sk = RECOVERED ERROR
@@ -875,63 +947,6 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
*/
scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D);
}
-
- if ((sb[0] & 0x7f) >= 0x72) {
- unsigned char *desc;
- u8 len;
-
- /* descriptor format */
- len = sb[7];
- desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
- if (!desc) {
- if (SCSI_SENSE_BUFFERSIZE < len + 14)
- return;
- sb[7] = len + 14;
- desc = sb + 8 + len;
- }
- desc[0] = 9;
- desc[1] = 12;
- /*
- * Copy registers into sense buffer.
- */
- desc[2] = 0x00;
- desc[3] = tf->error;
- desc[5] = tf->nsect;
- desc[7] = tf->lbal;
- desc[9] = tf->lbam;
- desc[11] = tf->lbah;
- desc[12] = tf->device;
- desc[13] = tf->status;
-
- /*
- * Fill in Extend bit, and the high order bytes
- * if applicable.
- */
- if (tf->flags & ATA_TFLAG_LBA48) {
- desc[2] |= 0x01;
- desc[4] = tf->hob_nsect;
- desc[6] = tf->hob_lbal;
- desc[8] = tf->hob_lbam;
- desc[10] = tf->hob_lbah;
- }
- } else {
- /* Fixed sense format */
- sb[0] |= 0x80;
- sb[3] = tf->error;
- sb[4] = tf->status;
- sb[5] = tf->device;
- sb[6] = tf->nsect;
- if (tf->flags & ATA_TFLAG_LBA48) {
- sb[8] |= 0x80;
- if (tf->hob_nsect)
- sb[8] |= 0x40;
- if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
- sb[8] |= 0x20;
- }
- sb[9] = tf->lbal;
- sb[10] = tf->lbam;
- sb[11] = tf->lbah;
- }
}
/**
@@ -1634,6 +1649,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
u8 *cdb = cmd->cmnd;
int need_sense = (qc->err_mask != 0) &&
!(qc->flags & ATA_QCFLAG_SENSE_VALID);
+ int need_passthru_sense = (qc->err_mask != 0) ||
+ (qc->flags & ATA_QCFLAG_SENSE_VALID);
/* For ATA pass thru (SAT) commands, generate a sense block if
* user mandated it or if there's an error. Note that if we
@@ -1645,13 +1662,16 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE
*/
if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
- ((cdb[2] & 0x20) || need_sense))
- ata_gen_passthru_sense(qc);
- else if (need_sense)
+ ((cdb[2] & 0x20) || need_passthru_sense)) {
+ if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
+ ata_gen_passthru_sense(qc);
+ ata_scsi_set_passthru_sense_fields(qc);
+ } else if (need_sense) {
ata_gen_ata_sense(qc);
- else
+ } else {
/* Keep the SCSI ML and status byte, clear host byte. */
cmd->result &= 0x0000ffff;
+ }
ata_qc_done(qc);
}
@@ -2590,14 +2610,8 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
/* handle completion from EH */
if (unlikely(err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID)) {
- if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
- /* FIXME: not quite right; we don't want the
- * translation of taskfile registers into a
- * sense descriptors, since that's only
- * correct for ATA, not ATAPI
- */
+ if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
ata_gen_passthru_sense(qc);
- }
/* SCSI EH automatically locks door if sdev->locked is
* set. Sometimes door lock request continues to
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v4 2/8] ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1
2024-07-01 19:57 ` [PATCH v4 2/8] ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1 Igor Pylypiv
@ 2024-07-01 21:15 ` Niklas Cassel
0 siblings, 0 replies; 18+ messages in thread
From: Niklas Cassel @ 2024-07-01 21:15 UTC (permalink / raw)
To: Igor Pylypiv
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel, stable
On Mon, Jul 01, 2024 at 07:57:52PM +0000, Igor Pylypiv wrote:
> Current ata_gen_passthru_sense() code performs two actions:
> 1. Generates sense data based on the ATA 'status' and ATA 'error' fields.
> 2. Populates "ATA Status Return sense data descriptor" / "Fixed format
> sense data" with ATA taskfile fields.
>
> The problem is that #1 generates sense data even when a valid sense data
> is already present (ATA_QCFLAG_SENSE_VALID is set). Factoring out #2 into
> a separate function allows us to generate sense data only when there is
> no valid sense data (ATA_QCFLAG_SENSE_VALID is not set).
>
> As a bonus, we can now delete a FIXME comment in atapi_qc_complete()
> which states that we don't want to translate taskfile registers into
> sense descriptors for ATAPI.
>
> Cc: stable@vger.kernel.org # 4.19+
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
> Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> ---
> drivers/ata/libata-scsi.c | 158 +++++++++++++++++++++-----------------
> 1 file changed, 86 insertions(+), 72 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index a9e44ad4c2de..26b1263f5c7c 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -230,6 +230,80 @@ void ata_scsi_set_sense_information(struct ata_device *dev,
> SCSI_SENSE_BUFFERSIZE, information);
> }
>
> +/**
> + * ata_scsi_set_passthru_sense_fields - Set ATA fields in sense buffer
> + * @qc: ATA PASS-THROUGH command.
> + *
> + * Populates "ATA Status Return sense data descriptor" / "Fixed format
> + * sense data" with ATA taskfile fields.
> + *
> + * LOCKING:
> + * None.
> + */
> +static void ata_scsi_set_passthru_sense_fields(struct ata_queued_cmd *qc)
> +{
> + struct scsi_cmnd *cmd = qc->scsicmd;
> + struct ata_taskfile *tf = &qc->result_tf;
> + unsigned char *sb = cmd->sense_buffer;
> +
> + if ((sb[0] & 0x7f) >= 0x72) {
> + unsigned char *desc;
> + u8 len;
> +
> + /* descriptor format */
> + len = sb[7];
> + desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
> + if (!desc) {
> + if (SCSI_SENSE_BUFFERSIZE < len + 14)
> + return;
> + sb[7] = len + 14;
> + desc = sb + 8 + len;
> + }
> + desc[0] = 9;
> + desc[1] = 12;
> + /*
> + * Copy registers into sense buffer.
> + */
> + desc[2] = 0x00;
> + desc[3] = tf->error;
> + desc[5] = tf->nsect;
> + desc[7] = tf->lbal;
> + desc[9] = tf->lbam;
> + desc[11] = tf->lbah;
> + desc[12] = tf->device;
> + desc[13] = tf->status;
> +
> + /*
> + * Fill in Extend bit, and the high order bytes
> + * if applicable.
> + */
> + if (tf->flags & ATA_TFLAG_LBA48) {
> + desc[2] |= 0x01;
> + desc[4] = tf->hob_nsect;
> + desc[6] = tf->hob_lbal;
> + desc[8] = tf->hob_lbam;
> + desc[10] = tf->hob_lbah;
> + }
> + } else {
> + /* Fixed sense format */
> + sb[0] |= 0x80;
> + sb[3] = tf->error;
> + sb[4] = tf->status;
> + sb[5] = tf->device;
> + sb[6] = tf->nsect;
> + if (tf->flags & ATA_TFLAG_LBA48) {
> + sb[8] |= 0x80;
> + if (tf->hob_nsect)
> + sb[8] |= 0x40;
> + if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
> + sb[8] |= 0x20;
> + }
> + sb[9] = tf->lbal;
> + sb[10] = tf->lbam;
> + sb[11] = tf->lbah;
> + }
> +}
> +
> static void ata_scsi_set_invalid_field(struct ata_device *dev,
> struct scsi_cmnd *cmd, u16 field, u8 bit)
> {
> @@ -837,10 +911,8 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
> * ata_gen_passthru_sense - Generate check condition sense block.
> * @qc: Command that completed.
> *
> - * This function is specific to the ATA descriptor format sense
> - * block specified for the ATA pass through commands. Regardless
> - * of whether the command errored or not, return a sense
> - * block. Copy all controller registers into the sense
> + * This function is specific to the ATA pass through commands.
> + * Regardless of whether the command errored or not, return a sense
> * block. If there was no error, we get the request from an ATA
> * passthrough command, so we use the following sense data:
> * sk = RECOVERED ERROR
> @@ -875,63 +947,6 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> */
> scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D);
> }
> -
> - if ((sb[0] & 0x7f) >= 0x72) {
> - unsigned char *desc;
> - u8 len;
> -
> - /* descriptor format */
> - len = sb[7];
> - desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
> - if (!desc) {
> - if (SCSI_SENSE_BUFFERSIZE < len + 14)
> - return;
> - sb[7] = len + 14;
> - desc = sb + 8 + len;
> - }
> - desc[0] = 9;
> - desc[1] = 12;
> - /*
> - * Copy registers into sense buffer.
> - */
> - desc[2] = 0x00;
> - desc[3] = tf->error;
> - desc[5] = tf->nsect;
> - desc[7] = tf->lbal;
> - desc[9] = tf->lbam;
> - desc[11] = tf->lbah;
> - desc[12] = tf->device;
> - desc[13] = tf->status;
> -
> - /*
> - * Fill in Extend bit, and the high order bytes
> - * if applicable.
> - */
> - if (tf->flags & ATA_TFLAG_LBA48) {
> - desc[2] |= 0x01;
> - desc[4] = tf->hob_nsect;
> - desc[6] = tf->hob_lbal;
> - desc[8] = tf->hob_lbam;
> - desc[10] = tf->hob_lbah;
> - }
> - } else {
> - /* Fixed sense format */
> - sb[0] |= 0x80;
> - sb[3] = tf->error;
> - sb[4] = tf->status;
> - sb[5] = tf->device;
> - sb[6] = tf->nsect;
> - if (tf->flags & ATA_TFLAG_LBA48) {
> - sb[8] |= 0x80;
> - if (tf->hob_nsect)
> - sb[8] |= 0x40;
> - if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
> - sb[8] |= 0x20;
> - }
> - sb[9] = tf->lbal;
> - sb[10] = tf->lbam;
> - sb[11] = tf->lbah;
> - }
> }
>
> /**
> @@ -1634,6 +1649,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
> u8 *cdb = cmd->cmnd;
> int need_sense = (qc->err_mask != 0) &&
> !(qc->flags & ATA_QCFLAG_SENSE_VALID);
> + int need_passthru_sense = (qc->err_mask != 0) ||
> + (qc->flags & ATA_QCFLAG_SENSE_VALID);
>
> /* For ATA pass thru (SAT) commands, generate a sense block if
> * user mandated it or if there's an error. Note that if we
> @@ -1645,13 +1662,16 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
> * asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE
> */
> if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
> - ((cdb[2] & 0x20) || need_sense))
> - ata_gen_passthru_sense(qc);
> - else if (need_sense)
> + ((cdb[2] & 0x20) || need_passthru_sense)) {
> + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
> + ata_gen_passthru_sense(qc);
> + ata_scsi_set_passthru_sense_fields(qc);
> + } else if (need_sense) {
> ata_gen_ata_sense(qc);
> - else
> + } else {
> /* Keep the SCSI ML and status byte, clear host byte. */
> cmd->result &= 0x0000ffff;
> + }
>
> ata_qc_done(qc);
> }
> @@ -2590,14 +2610,8 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
> /* handle completion from EH */
> if (unlikely(err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID)) {
>
> - if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
> - /* FIXME: not quite right; we don't want the
> - * translation of taskfile registers into a
> - * sense descriptors, since that's only
> - * correct for ATA, not ATAPI
> - */
> + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
> ata_gen_passthru_sense(qc);
> - }
>
> /* SCSI EH automatically locks door if sdev->locked is
> * set. Sometimes door lock request continues to
> --
> 2.45.2.803.g4e1b14247a-goog
>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
However: I really think that this patch should be squashed with patch 8/8.
For more details, see my reply to patch 8/8.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 3/8] ata: libata-scsi: Honour the D_SENSE bit for CK_COND=1 and no error
2024-07-01 19:57 [PATCH v4 0/8] ATA PASS-THROUGH sense data fixes Igor Pylypiv
2024-07-01 19:57 ` [PATCH v4 1/8] ata: libata-scsi: Fix offsets for the fixed format sense data Igor Pylypiv
2024-07-01 19:57 ` [PATCH v4 2/8] ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1 Igor Pylypiv
@ 2024-07-01 19:57 ` Igor Pylypiv
2024-07-01 21:12 ` Niklas Cassel
2024-07-01 19:57 ` [PATCH v4 4/8] ata: libata-scsi: Remove redundant sense_buffer memsets Igor Pylypiv
` (4 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-01 19:57 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: Tejun Heo, Hannes Reinecke, linux-ide, linux-kernel, Igor Pylypiv,
stable
SAT-5 revision 8 specification removed the text about the ANSI INCITS
431-2007 compliance which was requiring SCSI/ATA Translation (SAT) to
return descriptor format sense data for the ATA PASS-THROUGH commands
regardless of the setting of the D_SENSE bit.
Let's honour the D_SENSE bit for CK_COND=1 commands that had no error.
Kernel already honours the D_SENSE bit when creating the sense buffer
for commands that had an error.
SAT-5 revision 7
================
12.2.2.8 Fixed format sense data
Table 212 shows the fields returned in the fixed format sense data
(see SPC-5) for ATA PASS-THROUGH commands. SATLs compliant with ANSI
INCITS 431-2007, SCSI/ATA Translation (SAT) return descriptor format
sense data for the ATA PASS-THROUGH commands regardless of the setting
of the D_SENSE bit.
SAT-5 revision 8
================
12.2.2.8 Fixed format sense data
Table 211 shows the fields returned in the fixed format sense data
(see SPC-5) for ATA PASS-THROUGH commands.
Cc: stable@vger.kernel.org # 4.19+
Reported-by: Niklas Cassel <cassel@kernel.org>
Closes: https://lore.kernel.org/linux-ide/Zn1WUhmLglM4iais@ryzen.lan
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
drivers/ata/libata-scsi.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 26b1263f5c7c..ace6b009e7ff 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -941,11 +941,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
&sense_key, &asc, &ascq);
ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq);
} else {
- /*
- * ATA PASS-THROUGH INFORMATION AVAILABLE
- * Always in descriptor format sense.
- */
- scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D);
+ /* ATA PASS-THROUGH INFORMATION AVAILABLE */
+ ata_scsi_set_sense(qc->dev, cmd, RECOVERED_ERROR, 0, 0x1D);
}
}
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v4 3/8] ata: libata-scsi: Honour the D_SENSE bit for CK_COND=1 and no error
2024-07-01 19:57 ` [PATCH v4 3/8] ata: libata-scsi: Honour the D_SENSE bit for CK_COND=1 and no error Igor Pylypiv
@ 2024-07-01 21:12 ` Niklas Cassel
0 siblings, 0 replies; 18+ messages in thread
From: Niklas Cassel @ 2024-07-01 21:12 UTC (permalink / raw)
To: Igor Pylypiv
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel, stable
On Mon, Jul 01, 2024 at 07:57:53PM +0000, Igor Pylypiv wrote:
> SAT-5 revision 8 specification removed the text about the ANSI INCITS
> 431-2007 compliance which was requiring SCSI/ATA Translation (SAT) to
> return descriptor format sense data for the ATA PASS-THROUGH commands
> regardless of the setting of the D_SENSE bit.
>
> Let's honour the D_SENSE bit for CK_COND=1 commands that had no error.
> Kernel already honours the D_SENSE bit when creating the sense buffer
> for commands that had an error.
Nit: we also honor it when creating the sense buffer for successful NCQ
commands (e.g. CDL policy 0xD).
>
> SAT-5 revision 7
> ================
>
> 12.2.2.8 Fixed format sense data
>
> Table 212 shows the fields returned in the fixed format sense data
> (see SPC-5) for ATA PASS-THROUGH commands. SATLs compliant with ANSI
> INCITS 431-2007, SCSI/ATA Translation (SAT) return descriptor format
> sense data for the ATA PASS-THROUGH commands regardless of the setting
> of the D_SENSE bit.
>
> SAT-5 revision 8
> ================
>
> 12.2.2.8 Fixed format sense data
>
> Table 211 shows the fields returned in the fixed format sense data
> (see SPC-5) for ATA PASS-THROUGH commands.
>
> Cc: stable@vger.kernel.org # 4.19+
> Reported-by: Niklas Cassel <cassel@kernel.org>
> Closes: https://lore.kernel.org/linux-ide/Zn1WUhmLglM4iais@ryzen.lan
> Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> ---
> drivers/ata/libata-scsi.c | 7 ++-----
> 1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 26b1263f5c7c..ace6b009e7ff 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -941,11 +941,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> &sense_key, &asc, &ascq);
> ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq);
> } else {
> - /*
> - * ATA PASS-THROUGH INFORMATION AVAILABLE
> - * Always in descriptor format sense.
> - */
> - scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D);
> + /* ATA PASS-THROUGH INFORMATION AVAILABLE */
> + ata_scsi_set_sense(qc->dev, cmd, RECOVERED_ERROR, 0, 0x1D);
> }
> }
>
> --
> 2.45.2.803.g4e1b14247a-goog
>
With or without nit fixed:
Reviewed-by: Niklas Cassel <cassel@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 4/8] ata: libata-scsi: Remove redundant sense_buffer memsets
2024-07-01 19:57 [PATCH v4 0/8] ATA PASS-THROUGH sense data fixes Igor Pylypiv
` (2 preceding siblings ...)
2024-07-01 19:57 ` [PATCH v4 3/8] ata: libata-scsi: Honour the D_SENSE bit for CK_COND=1 and no error Igor Pylypiv
@ 2024-07-01 19:57 ` Igor Pylypiv
2024-07-01 21:12 ` Niklas Cassel
2024-07-01 19:57 ` [PATCH v4 5/8] ata: libata-scsi: Do not pass ATA device id to ata_to_sense_error() Igor Pylypiv
` (3 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-01 19:57 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: Tejun Heo, Hannes Reinecke, linux-ide, linux-kernel, Igor Pylypiv
SCSI layer clears sense_buffer in scsi_queue_rq() so there is no need for
libata to clear it again.
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
drivers/ata/libata-scsi.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index ace6b009e7ff..c11ae77d3ca6 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -926,11 +926,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->result_tf;
- unsigned char *sb = cmd->sense_buffer;
u8 sense_key, asc, ascq;
- memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
-
/*
* Use ata_to_sense_error() to map status register bits
* onto sense key, asc & ascq.
@@ -965,8 +962,6 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
u64 block;
u8 sense_key, asc, ascq;
- memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
-
if (ata_dev_disabled(dev)) {
/* Device disabled after error recovery */
/* LOGICAL UNIT NOT READY, HARD RESET REQUIRED */
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v4 4/8] ata: libata-scsi: Remove redundant sense_buffer memsets
2024-07-01 19:57 ` [PATCH v4 4/8] ata: libata-scsi: Remove redundant sense_buffer memsets Igor Pylypiv
@ 2024-07-01 21:12 ` Niklas Cassel
0 siblings, 0 replies; 18+ messages in thread
From: Niklas Cassel @ 2024-07-01 21:12 UTC (permalink / raw)
To: Igor Pylypiv
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel
On Mon, Jul 01, 2024 at 07:57:54PM +0000, Igor Pylypiv wrote:
> SCSI layer clears sense_buffer in scsi_queue_rq() so there is no need for
> libata to clear it again.
>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
> Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> ---
> drivers/ata/libata-scsi.c | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index ace6b009e7ff..c11ae77d3ca6 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -926,11 +926,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> {
> struct scsi_cmnd *cmd = qc->scsicmd;
> struct ata_taskfile *tf = &qc->result_tf;
> - unsigned char *sb = cmd->sense_buffer;
> u8 sense_key, asc, ascq;
>
> - memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
> -
> /*
> * Use ata_to_sense_error() to map status register bits
> * onto sense key, asc & ascq.
> @@ -965,8 +962,6 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
> u64 block;
> u8 sense_key, asc, ascq;
>
> - memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
> -
> if (ata_dev_disabled(dev)) {
> /* Device disabled after error recovery */
> /* LOGICAL UNIT NOT READY, HARD RESET REQUIRED */
> --
> 2.45.2.803.g4e1b14247a-goog
>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 5/8] ata: libata-scsi: Do not pass ATA device id to ata_to_sense_error()
2024-07-01 19:57 [PATCH v4 0/8] ATA PASS-THROUGH sense data fixes Igor Pylypiv
` (3 preceding siblings ...)
2024-07-01 19:57 ` [PATCH v4 4/8] ata: libata-scsi: Remove redundant sense_buffer memsets Igor Pylypiv
@ 2024-07-01 19:57 ` Igor Pylypiv
2024-07-01 21:12 ` Niklas Cassel
2024-07-01 19:57 ` [PATCH v4 6/8] ata: libata-core: Set ATA_QCFLAG_RTF_FILLED in fill_result_tf() Igor Pylypiv
` (2 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-01 19:57 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: Tejun Heo, Hannes Reinecke, linux-ide, linux-kernel, Igor Pylypiv
ATA device id is not used in ata_to_sense_error().
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
drivers/ata/libata-scsi.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index c11ae77d3ca6..92d75780fc3b 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -785,7 +785,6 @@ static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc)
/**
* ata_to_sense_error - convert ATA error to SCSI error
- * @id: ATA device number
* @drv_stat: value contained in ATA status register
* @drv_err: value contained in ATA error register
* @sk: the sense key we'll fill out
@@ -799,8 +798,8 @@ static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
- u8 *asc, u8 *ascq)
+static void ata_to_sense_error(u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
+ u8 *ascq)
{
int i;
@@ -934,7 +933,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
*/
if (qc->err_mask ||
tf->status & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
- ata_to_sense_error(qc->ap->print_id, tf->status, tf->error,
+ ata_to_sense_error(tf->status, tf->error,
&sense_key, &asc, &ascq);
ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq);
} else {
@@ -973,7 +972,7 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
*/
if (qc->err_mask ||
tf->status & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
- ata_to_sense_error(qc->ap->print_id, tf->status, tf->error,
+ ata_to_sense_error(tf->status, tf->error,
&sense_key, &asc, &ascq);
ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq);
} else {
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v4 5/8] ata: libata-scsi: Do not pass ATA device id to ata_to_sense_error()
2024-07-01 19:57 ` [PATCH v4 5/8] ata: libata-scsi: Do not pass ATA device id to ata_to_sense_error() Igor Pylypiv
@ 2024-07-01 21:12 ` Niklas Cassel
0 siblings, 0 replies; 18+ messages in thread
From: Niklas Cassel @ 2024-07-01 21:12 UTC (permalink / raw)
To: Igor Pylypiv
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel
On Mon, Jul 01, 2024 at 07:57:55PM +0000, Igor Pylypiv wrote:
> ATA device id is not used in ata_to_sense_error().
>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
> Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> ---
> drivers/ata/libata-scsi.c | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index c11ae77d3ca6..92d75780fc3b 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -785,7 +785,6 @@ static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc)
>
> /**
> * ata_to_sense_error - convert ATA error to SCSI error
> - * @id: ATA device number
> * @drv_stat: value contained in ATA status register
> * @drv_err: value contained in ATA error register
> * @sk: the sense key we'll fill out
> @@ -799,8 +798,8 @@ static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc)
> * LOCKING:
> * spin_lock_irqsave(host lock)
> */
> -static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
> - u8 *asc, u8 *ascq)
> +static void ata_to_sense_error(u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
> + u8 *ascq)
> {
> int i;
>
> @@ -934,7 +933,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> */
> if (qc->err_mask ||
> tf->status & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
> - ata_to_sense_error(qc->ap->print_id, tf->status, tf->error,
> + ata_to_sense_error(tf->status, tf->error,
> &sense_key, &asc, &ascq);
> ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq);
> } else {
> @@ -973,7 +972,7 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
> */
> if (qc->err_mask ||
> tf->status & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
> - ata_to_sense_error(qc->ap->print_id, tf->status, tf->error,
> + ata_to_sense_error(tf->status, tf->error,
> &sense_key, &asc, &ascq);
> ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq);
> } else {
> --
> 2.45.2.803.g4e1b14247a-goog
>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 6/8] ata: libata-core: Set ATA_QCFLAG_RTF_FILLED in fill_result_tf()
2024-07-01 19:57 [PATCH v4 0/8] ATA PASS-THROUGH sense data fixes Igor Pylypiv
` (4 preceding siblings ...)
2024-07-01 19:57 ` [PATCH v4 5/8] ata: libata-scsi: Do not pass ATA device id to ata_to_sense_error() Igor Pylypiv
@ 2024-07-01 19:57 ` Igor Pylypiv
2024-07-01 21:13 ` Niklas Cassel
2024-07-01 19:57 ` [PATCH v4 7/8] ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf Igor Pylypiv
2024-07-01 19:57 ` [PATCH v4 8/8] ata: libata-scsi: Make ata_scsi_qc_complete() more readable Igor Pylypiv
7 siblings, 1 reply; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-01 19:57 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: Tejun Heo, Hannes Reinecke, linux-ide, linux-kernel, Igor Pylypiv
ATA_QCFLAG_RTF_FILLED is not specific to ahci and can be used generally
to check if qc->result_tf contains valid data.
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
drivers/ata/libahci.c | 12 ++----------
drivers/ata/libata-core.c | 8 ++++++++
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 83431aae74d8..fdfa7b266218 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -2075,13 +2075,6 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
struct ahci_port_priv *pp = qc->ap->private_data;
u8 *rx_fis = pp->rx_fis;
- /*
- * rtf may already be filled (e.g. for successful NCQ commands).
- * If that is the case, we have nothing to do.
- */
- if (qc->flags & ATA_QCFLAG_RTF_FILLED)
- return;
-
if (pp->fbs_enabled)
rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
@@ -2095,7 +2088,6 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
!(qc->flags & ATA_QCFLAG_EH)) {
ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15];
- qc->flags |= ATA_QCFLAG_RTF_FILLED;
return;
}
@@ -2118,12 +2110,10 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
*/
qc->result_tf.status = fis[2];
qc->result_tf.error = fis[3];
- qc->flags |= ATA_QCFLAG_RTF_FILLED;
return;
}
ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
- qc->flags |= ATA_QCFLAG_RTF_FILLED;
}
static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask)
@@ -2158,6 +2148,7 @@ static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask)
if (qc && ata_is_ncq(qc->tf.protocol)) {
qc->result_tf.status = status;
qc->result_tf.error = error;
+ qc->result_tf.flags = qc->tf.flags;
qc->flags |= ATA_QCFLAG_RTF_FILLED;
}
done_mask &= ~(1ULL << tag);
@@ -2182,6 +2173,7 @@ static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask)
fis += RX_FIS_SDB;
qc->result_tf.status = fis[2];
qc->result_tf.error = fis[3];
+ qc->result_tf.flags = qc->tf.flags;
qc->flags |= ATA_QCFLAG_RTF_FILLED;
}
done_mask &= ~(1ULL << tag);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 74b59b78d278..949662bc50e4 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4800,8 +4800,16 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ /*
+ * rtf may already be filled (e.g. for successful NCQ commands).
+ * If that is the case, we have nothing to do.
+ */
+ if (qc->flags & ATA_QCFLAG_RTF_FILLED)
+ return;
+
qc->result_tf.flags = qc->tf.flags;
ap->ops->qc_fill_rtf(qc);
+ qc->flags |= ATA_QCFLAG_RTF_FILLED;
}
static void ata_verify_xfer(struct ata_queued_cmd *qc)
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v4 6/8] ata: libata-core: Set ATA_QCFLAG_RTF_FILLED in fill_result_tf()
2024-07-01 19:57 ` [PATCH v4 6/8] ata: libata-core: Set ATA_QCFLAG_RTF_FILLED in fill_result_tf() Igor Pylypiv
@ 2024-07-01 21:13 ` Niklas Cassel
0 siblings, 0 replies; 18+ messages in thread
From: Niklas Cassel @ 2024-07-01 21:13 UTC (permalink / raw)
To: Igor Pylypiv
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel
On Mon, Jul 01, 2024 at 07:57:56PM +0000, Igor Pylypiv wrote:
> ATA_QCFLAG_RTF_FILLED is not specific to ahci and can be used generally
> to check if qc->result_tf contains valid data.
>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
> Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> ---
> drivers/ata/libahci.c | 12 ++----------
> drivers/ata/libata-core.c | 8 ++++++++
> 2 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
> index 83431aae74d8..fdfa7b266218 100644
> --- a/drivers/ata/libahci.c
> +++ b/drivers/ata/libahci.c
> @@ -2075,13 +2075,6 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
> struct ahci_port_priv *pp = qc->ap->private_data;
> u8 *rx_fis = pp->rx_fis;
>
> - /*
> - * rtf may already be filled (e.g. for successful NCQ commands).
> - * If that is the case, we have nothing to do.
> - */
> - if (qc->flags & ATA_QCFLAG_RTF_FILLED)
> - return;
> -
> if (pp->fbs_enabled)
> rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
>
> @@ -2095,7 +2088,6 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
> !(qc->flags & ATA_QCFLAG_EH)) {
> ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
> qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15];
> - qc->flags |= ATA_QCFLAG_RTF_FILLED;
> return;
> }
>
> @@ -2118,12 +2110,10 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
> */
> qc->result_tf.status = fis[2];
> qc->result_tf.error = fis[3];
> - qc->flags |= ATA_QCFLAG_RTF_FILLED;
> return;
> }
>
> ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
> - qc->flags |= ATA_QCFLAG_RTF_FILLED;
> }
>
> static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask)
> @@ -2158,6 +2148,7 @@ static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask)
> if (qc && ata_is_ncq(qc->tf.protocol)) {
> qc->result_tf.status = status;
> qc->result_tf.error = error;
> + qc->result_tf.flags = qc->tf.flags;
> qc->flags |= ATA_QCFLAG_RTF_FILLED;
> }
> done_mask &= ~(1ULL << tag);
> @@ -2182,6 +2173,7 @@ static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask)
> fis += RX_FIS_SDB;
> qc->result_tf.status = fis[2];
> qc->result_tf.error = fis[3];
> + qc->result_tf.flags = qc->tf.flags;
> qc->flags |= ATA_QCFLAG_RTF_FILLED;
> }
> done_mask &= ~(1ULL << tag);
> diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
> index 74b59b78d278..949662bc50e4 100644
> --- a/drivers/ata/libata-core.c
> +++ b/drivers/ata/libata-core.c
> @@ -4800,8 +4800,16 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
> {
> struct ata_port *ap = qc->ap;
>
> + /*
> + * rtf may already be filled (e.g. for successful NCQ commands).
> + * If that is the case, we have nothing to do.
> + */
> + if (qc->flags & ATA_QCFLAG_RTF_FILLED)
> + return;
> +
> qc->result_tf.flags = qc->tf.flags;
> ap->ops->qc_fill_rtf(qc);
> + qc->flags |= ATA_QCFLAG_RTF_FILLED;
> }
>
> static void ata_verify_xfer(struct ata_queued_cmd *qc)
> --
> 2.45.2.803.g4e1b14247a-goog
>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 7/8] ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf
2024-07-01 19:57 [PATCH v4 0/8] ATA PASS-THROUGH sense data fixes Igor Pylypiv
` (5 preceding siblings ...)
2024-07-01 19:57 ` [PATCH v4 6/8] ata: libata-core: Set ATA_QCFLAG_RTF_FILLED in fill_result_tf() Igor Pylypiv
@ 2024-07-01 19:57 ` Igor Pylypiv
2024-07-01 21:13 ` Niklas Cassel
2024-07-01 19:57 ` [PATCH v4 8/8] ata: libata-scsi: Make ata_scsi_qc_complete() more readable Igor Pylypiv
7 siblings, 1 reply; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-01 19:57 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: Tejun Heo, Hannes Reinecke, linux-ide, linux-kernel, Igor Pylypiv
qc->result_tf contents are only valid when the ATA_QCFLAG_RTF_FILLED flag
is set. The ATA_QCFLAG_RTF_FILLED flag should be always set for commands
that failed or for commands that have the ATA_QCFLAG_RESULT_TF flag set.
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
drivers/ata/libata-scsi.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 92d75780fc3b..a66c177b6087 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -242,10 +242,17 @@ void ata_scsi_set_sense_information(struct ata_device *dev,
*/
static void ata_scsi_set_passthru_sense_fields(struct ata_queued_cmd *qc)
{
+ struct ata_device *dev = qc->dev;
struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->result_tf;
unsigned char *sb = cmd->sense_buffer;
+ if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
+ ata_dev_dbg(dev,
+ "missing result TF: can't set ATA PT sense fields\n");
+ return;
+ }
+
if ((sb[0] & 0x7f) >= 0x72) {
unsigned char *desc;
u8 len;
@@ -923,10 +930,17 @@ static void ata_to_sense_error(u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
*/
static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
{
+ struct ata_device *dev = qc->dev;
struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->result_tf;
u8 sense_key, asc, ascq;
+ if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
+ ata_dev_dbg(dev,
+ "missing result TF: can't generate ATA PT sense data\n");
+ return;
+ }
+
/*
* Use ata_to_sense_error() to map status register bits
* onto sense key, asc & ascq.
@@ -967,6 +981,13 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
ata_scsi_set_sense(dev, cmd, NOT_READY, 0x04, 0x21);
return;
}
+
+ if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
+ ata_dev_dbg(dev,
+ "missing result TF: can't generate sense data\n");
+ return;
+ }
+
/* Use ata_to_sense_error() to map status register bits
* onto sense key, asc & ascq.
*/
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v4 7/8] ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf
2024-07-01 19:57 ` [PATCH v4 7/8] ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf Igor Pylypiv
@ 2024-07-01 21:13 ` Niklas Cassel
0 siblings, 0 replies; 18+ messages in thread
From: Niklas Cassel @ 2024-07-01 21:13 UTC (permalink / raw)
To: Igor Pylypiv
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel
On Mon, Jul 01, 2024 at 07:57:57PM +0000, Igor Pylypiv wrote:
> qc->result_tf contents are only valid when the ATA_QCFLAG_RTF_FILLED flag
> is set. The ATA_QCFLAG_RTF_FILLED flag should be always set for commands
> that failed or for commands that have the ATA_QCFLAG_RESULT_TF flag set.
>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
> Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> ---
> drivers/ata/libata-scsi.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 92d75780fc3b..a66c177b6087 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -242,10 +242,17 @@ void ata_scsi_set_sense_information(struct ata_device *dev,
> */
> static void ata_scsi_set_passthru_sense_fields(struct ata_queued_cmd *qc)
> {
> + struct ata_device *dev = qc->dev;
> struct scsi_cmnd *cmd = qc->scsicmd;
> struct ata_taskfile *tf = &qc->result_tf;
> unsigned char *sb = cmd->sense_buffer;
>
> + if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
> + ata_dev_dbg(dev,
> + "missing result TF: can't set ATA PT sense fields\n");
> + return;
> + }
> +
> if ((sb[0] & 0x7f) >= 0x72) {
> unsigned char *desc;
> u8 len;
> @@ -923,10 +930,17 @@ static void ata_to_sense_error(u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
> */
> static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
> {
> + struct ata_device *dev = qc->dev;
> struct scsi_cmnd *cmd = qc->scsicmd;
> struct ata_taskfile *tf = &qc->result_tf;
> u8 sense_key, asc, ascq;
>
> + if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
> + ata_dev_dbg(dev,
> + "missing result TF: can't generate ATA PT sense data\n");
> + return;
> + }
> +
> /*
> * Use ata_to_sense_error() to map status register bits
> * onto sense key, asc & ascq.
> @@ -967,6 +981,13 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
> ata_scsi_set_sense(dev, cmd, NOT_READY, 0x04, 0x21);
> return;
> }
> +
> + if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
> + ata_dev_dbg(dev,
> + "missing result TF: can't generate sense data\n");
> + return;
> + }
> +
> /* Use ata_to_sense_error() to map status register bits
> * onto sense key, asc & ascq.
> */
> --
> 2.45.2.803.g4e1b14247a-goog
>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 8/8] ata: libata-scsi: Make ata_scsi_qc_complete() more readable
2024-07-01 19:57 [PATCH v4 0/8] ATA PASS-THROUGH sense data fixes Igor Pylypiv
` (6 preceding siblings ...)
2024-07-01 19:57 ` [PATCH v4 7/8] ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf Igor Pylypiv
@ 2024-07-01 19:57 ` Igor Pylypiv
2024-07-01 21:15 ` Niklas Cassel
7 siblings, 1 reply; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-01 19:57 UTC (permalink / raw)
To: Damien Le Moal, Niklas Cassel
Cc: Tejun Heo, Hannes Reinecke, linux-ide, linux-kernel, Igor Pylypiv
The ATA PASS-THROUGH handling logic in ata_scsi_qc_complete() is hard
to read/understand. Improve the readability of the code by moving checks
into self-explanatory boolean variables.
Additionally, always set SAM_STAT_CHECK_CONDITION when CK_COND=1 because
SAT specification mandates that SATL shall return CHECK CONDITION if
the CK_COND bit is set.
Co-developed-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
---
drivers/ata/libata-scsi.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a66c177b6087..8f21b3b0bc75 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1659,26 +1659,27 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd;
- int need_sense = (qc->err_mask != 0) &&
- !(qc->flags & ATA_QCFLAG_SENSE_VALID);
- int need_passthru_sense = (qc->err_mask != 0) ||
- (qc->flags & ATA_QCFLAG_SENSE_VALID);
+ 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_error = qc->err_mask != 0;
/* For ATA pass thru (SAT) commands, generate a sense block if
* user mandated it or if there's an error. Note that if we
- * generate because the user forced us to [CK_COND =1], a check
+ * generate because the user forced us to [CK_COND=1], a check
* condition is generated and the ATA register values are returned
* whether the command completed successfully or not. If there
- * was no error, we use the following sense data:
+ * was no error, and CK_COND=1, we use the following sense data:
* sk = RECOVERED ERROR
* asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE
*/
- if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
- ((cdb[2] & 0x20) || need_passthru_sense)) {
- if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
+ if (is_ata_passthru && (is_ck_cond_request || is_error || have_sense)) {
+ if (!have_sense)
ata_gen_passthru_sense(qc);
ata_scsi_set_passthru_sense_fields(qc);
- } else if (need_sense) {
+ if (is_ck_cond_request)
+ set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION);
+ } else if (is_error && !have_sense) {
ata_gen_ata_sense(qc);
} else {
/* Keep the SCSI ML and status byte, clear host byte. */
--
2.45.2.803.g4e1b14247a-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v4 8/8] ata: libata-scsi: Make ata_scsi_qc_complete() more readable
2024-07-01 19:57 ` [PATCH v4 8/8] ata: libata-scsi: Make ata_scsi_qc_complete() more readable Igor Pylypiv
@ 2024-07-01 21:15 ` Niklas Cassel
2024-07-02 2:50 ` Igor Pylypiv
0 siblings, 1 reply; 18+ messages in thread
From: Niklas Cassel @ 2024-07-01 21:15 UTC (permalink / raw)
To: Igor Pylypiv
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel
On Mon, Jul 01, 2024 at 07:57:58PM +0000, Igor Pylypiv wrote:
> The ATA PASS-THROUGH handling logic in ata_scsi_qc_complete() is hard
> to read/understand. Improve the readability of the code by moving checks
> into self-explanatory boolean variables.
>
> Additionally, always set SAM_STAT_CHECK_CONDITION when CK_COND=1 because
> SAT specification mandates that SATL shall return CHECK CONDITION if
> the CK_COND bit is set.
>
> Co-developed-by: Niklas Cassel <cassel@kernel.org>
> Signed-off-by: Niklas Cassel <cassel@kernel.org>
> Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> ---
> drivers/ata/libata-scsi.c | 21 +++++++++++----------
> 1 file changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index a66c177b6087..8f21b3b0bc75 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -1659,26 +1659,27 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
> {
> struct scsi_cmnd *cmd = qc->scsicmd;
> u8 *cdb = cmd->cmnd;
> - int need_sense = (qc->err_mask != 0) &&
> - !(qc->flags & ATA_QCFLAG_SENSE_VALID);
> - int need_passthru_sense = (qc->err_mask != 0) ||
> - (qc->flags & ATA_QCFLAG_SENSE_VALID);
> + 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_error = qc->err_mask != 0;
>
> /* For ATA pass thru (SAT) commands, generate a sense block if
> * user mandated it or if there's an error. Note that if we
> - * generate because the user forced us to [CK_COND =1], a check
> + * generate because the user forced us to [CK_COND=1], a check
> * condition is generated and the ATA register values are returned
> * whether the command completed successfully or not. If there
> - * was no error, we use the following sense data:
> + * was no error, and CK_COND=1, we use the following sense data:
> * sk = RECOVERED ERROR
> * asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE
> */
> - if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
> - ((cdb[2] & 0x20) || need_passthru_sense)) {
> - if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
> + if (is_ata_passthru && (is_ck_cond_request || is_error || have_sense)) {
> + if (!have_sense)
> ata_gen_passthru_sense(qc);
> ata_scsi_set_passthru_sense_fields(qc);
> - } else if (need_sense) {
> + if (is_ck_cond_request)
> + set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION);
> + } else if (is_error && !have_sense) {
> ata_gen_ata_sense(qc);
> } else {
> /* Keep the SCSI ML and status byte, clear host byte. */
> --
> 2.45.2.803.g4e1b14247a-goog
>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
However: I really think that this patch should be squashed with patch 2/8.
Sure, the changes in this patch will make it harder to backport...
but, even patch 2/8 will be a pain to backport...
And this patch will need to have CC: stable and be backported as well...
(such that we always set CHECK_CONDITION when CK_COND=1), so I strongly
suggest that we should squash these, since it will probably be way simpler
to backport the patch that is "patch 2/8 squashed with this patch",
compared to backporting patch 2/8, and then backporting this patch.
(That would just give two patches that will need manual backport, rather
than one patch that needs manual backport.)
Both of these are fixing incorrect sense data for ATA passthough commands
anyway.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH v4 8/8] ata: libata-scsi: Make ata_scsi_qc_complete() more readable
2024-07-01 21:15 ` Niklas Cassel
@ 2024-07-02 2:50 ` Igor Pylypiv
0 siblings, 0 replies; 18+ messages in thread
From: Igor Pylypiv @ 2024-07-02 2:50 UTC (permalink / raw)
To: Niklas Cassel
Cc: Damien Le Moal, Tejun Heo, Hannes Reinecke, linux-ide,
linux-kernel
On Mon, Jul 01, 2024 at 11:15:54PM +0200, Niklas Cassel wrote:
> On Mon, Jul 01, 2024 at 07:57:58PM +0000, Igor Pylypiv wrote:
> > The ATA PASS-THROUGH handling logic in ata_scsi_qc_complete() is hard
> > to read/understand. Improve the readability of the code by moving checks
> > into self-explanatory boolean variables.
> >
> > Additionally, always set SAM_STAT_CHECK_CONDITION when CK_COND=1 because
> > SAT specification mandates that SATL shall return CHECK CONDITION if
> > the CK_COND bit is set.
> >
> > Co-developed-by: Niklas Cassel <cassel@kernel.org>
> > Signed-off-by: Niklas Cassel <cassel@kernel.org>
> > Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
> > ---
> > drivers/ata/libata-scsi.c | 21 +++++++++++----------
> > 1 file changed, 11 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> > index a66c177b6087..8f21b3b0bc75 100644
> > --- a/drivers/ata/libata-scsi.c
> > +++ b/drivers/ata/libata-scsi.c
> > @@ -1659,26 +1659,27 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
> > {
> > struct scsi_cmnd *cmd = qc->scsicmd;
> > u8 *cdb = cmd->cmnd;
> > - int need_sense = (qc->err_mask != 0) &&
> > - !(qc->flags & ATA_QCFLAG_SENSE_VALID);
> > - int need_passthru_sense = (qc->err_mask != 0) ||
> > - (qc->flags & ATA_QCFLAG_SENSE_VALID);
> > + 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_error = qc->err_mask != 0;
> >
> > /* For ATA pass thru (SAT) commands, generate a sense block if
> > * user mandated it or if there's an error. Note that if we
> > - * generate because the user forced us to [CK_COND =1], a check
> > + * generate because the user forced us to [CK_COND=1], a check
> > * condition is generated and the ATA register values are returned
> > * whether the command completed successfully or not. If there
> > - * was no error, we use the following sense data:
> > + * was no error, and CK_COND=1, we use the following sense data:
> > * sk = RECOVERED ERROR
> > * asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE
> > */
> > - if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
> > - ((cdb[2] & 0x20) || need_passthru_sense)) {
> > - if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
> > + if (is_ata_passthru && (is_ck_cond_request || is_error || have_sense)) {
> > + if (!have_sense)
> > ata_gen_passthru_sense(qc);
> > ata_scsi_set_passthru_sense_fields(qc);
> > - } else if (need_sense) {
> > + if (is_ck_cond_request)
> > + set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION);
> > + } else if (is_error && !have_sense) {
> > ata_gen_ata_sense(qc);
> > } else {
> > /* Keep the SCSI ML and status byte, clear host byte. */
> > --
> > 2.45.2.803.g4e1b14247a-goog
> >
>
> Reviewed-by: Niklas Cassel <cassel@kernel.org>
>
> However: I really think that this patch should be squashed with patch 2/8.
>
> Sure, the changes in this patch will make it harder to backport...
> but, even patch 2/8 will be a pain to backport...
>
> And this patch will need to have CC: stable and be backported as well...
> (such that we always set CHECK_CONDITION when CK_COND=1), so I strongly
> suggest that we should squash these, since it will probably be way simpler
> to backport the patch that is "patch 2/8 squashed with this patch",
> compared to backporting patch 2/8, and then backporting this patch.
> (That would just give two patches that will need manual backport, rather
> than one patch that needs manual backport.)
>
> Both of these are fixing incorrect sense data for ATA passthough commands
> anyway.
Agreed, it makes more sense to squash. Squashed the patches in v5.
I really appreciate your thorough reviews and feedback, Niklas! Thank you!
Best,
Igor
>
>
> Kind regards,
> Niklas
^ permalink raw reply [flat|nested] 18+ messages in thread