Skip to content

Commit 9798192

Browse files
ipylypivfloatious
authored andcommitted
ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1
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. 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. 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. Cc: [email protected] # 4.19+ Co-developed-by: Niklas Cassel <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Reviewed-by: Damien Le Moal <[email protected]> Reviewed-by: Niklas Cassel <[email protected]> Signed-off-by: Igor Pylypiv <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Niklas Cassel <[email protected]>
1 parent 38dab83 commit 9798192

File tree

1 file changed

+92
-77
lines changed

1 file changed

+92
-77
lines changed

drivers/ata/libata-scsi.c

Lines changed: 92 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,80 @@ void ata_scsi_set_sense_information(struct ata_device *dev,
230230
SCSI_SENSE_BUFFERSIZE, information);
231231
}
232232

233+
/**
234+
* ata_scsi_set_passthru_sense_fields - Set ATA fields in sense buffer
235+
* @qc: ATA PASS-THROUGH command.
236+
*
237+
* Populates "ATA Status Return sense data descriptor" / "Fixed format
238+
* sense data" with ATA taskfile fields.
239+
*
240+
* LOCKING:
241+
* None.
242+
*/
243+
static void ata_scsi_set_passthru_sense_fields(struct ata_queued_cmd *qc)
244+
{
245+
struct scsi_cmnd *cmd = qc->scsicmd;
246+
struct ata_taskfile *tf = &qc->result_tf;
247+
unsigned char *sb = cmd->sense_buffer;
248+
249+
if ((sb[0] & 0x7f) >= 0x72) {
250+
unsigned char *desc;
251+
u8 len;
252+
253+
/* descriptor format */
254+
len = sb[7];
255+
desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
256+
if (!desc) {
257+
if (SCSI_SENSE_BUFFERSIZE < len + 14)
258+
return;
259+
sb[7] = len + 14;
260+
desc = sb + 8 + len;
261+
}
262+
desc[0] = 9;
263+
desc[1] = 12;
264+
/*
265+
* Copy registers into sense buffer.
266+
*/
267+
desc[2] = 0x00;
268+
desc[3] = tf->error;
269+
desc[5] = tf->nsect;
270+
desc[7] = tf->lbal;
271+
desc[9] = tf->lbam;
272+
desc[11] = tf->lbah;
273+
desc[12] = tf->device;
274+
desc[13] = tf->status;
275+
276+
/*
277+
* Fill in Extend bit, and the high order bytes
278+
* if applicable.
279+
*/
280+
if (tf->flags & ATA_TFLAG_LBA48) {
281+
desc[2] |= 0x01;
282+
desc[4] = tf->hob_nsect;
283+
desc[6] = tf->hob_lbal;
284+
desc[8] = tf->hob_lbam;
285+
desc[10] = tf->hob_lbah;
286+
}
287+
} else {
288+
/* Fixed sense format */
289+
sb[0] |= 0x80;
290+
sb[3] = tf->error;
291+
sb[4] = tf->status;
292+
sb[5] = tf->device;
293+
sb[6] = tf->nsect;
294+
if (tf->flags & ATA_TFLAG_LBA48) {
295+
sb[8] |= 0x80;
296+
if (tf->hob_nsect)
297+
sb[8] |= 0x40;
298+
if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
299+
sb[8] |= 0x20;
300+
}
301+
sb[9] = tf->lbal;
302+
sb[10] = tf->lbam;
303+
sb[11] = tf->lbah;
304+
}
305+
}
306+
233307
static void ata_scsi_set_invalid_field(struct ata_device *dev,
234308
struct scsi_cmnd *cmd, u16 field, u8 bit)
235309
{
@@ -837,10 +911,8 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
837911
* ata_gen_passthru_sense - Generate check condition sense block.
838912
* @qc: Command that completed.
839913
*
840-
* This function is specific to the ATA descriptor format sense
841-
* block specified for the ATA pass through commands. Regardless
842-
* of whether the command errored or not, return a sense
843-
* block. Copy all controller registers into the sense
914+
* This function is specific to the ATA pass through commands.
915+
* Regardless of whether the command errored or not, return a sense
844916
* block. If there was no error, we get the request from an ATA
845917
* passthrough command, so we use the following sense data:
846918
* sk = RECOVERED ERROR
@@ -875,63 +947,6 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
875947
*/
876948
scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D);
877949
}
878-
879-
if ((sb[0] & 0x7f) >= 0x72) {
880-
unsigned char *desc;
881-
u8 len;
882-
883-
/* descriptor format */
884-
len = sb[7];
885-
desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
886-
if (!desc) {
887-
if (SCSI_SENSE_BUFFERSIZE < len + 14)
888-
return;
889-
sb[7] = len + 14;
890-
desc = sb + 8 + len;
891-
}
892-
desc[0] = 9;
893-
desc[1] = 12;
894-
/*
895-
* Copy registers into sense buffer.
896-
*/
897-
desc[2] = 0x00;
898-
desc[3] = tf->error;
899-
desc[5] = tf->nsect;
900-
desc[7] = tf->lbal;
901-
desc[9] = tf->lbam;
902-
desc[11] = tf->lbah;
903-
desc[12] = tf->device;
904-
desc[13] = tf->status;
905-
906-
/*
907-
* Fill in Extend bit, and the high order bytes
908-
* if applicable.
909-
*/
910-
if (tf->flags & ATA_TFLAG_LBA48) {
911-
desc[2] |= 0x01;
912-
desc[4] = tf->hob_nsect;
913-
desc[6] = tf->hob_lbal;
914-
desc[8] = tf->hob_lbam;
915-
desc[10] = tf->hob_lbah;
916-
}
917-
} else {
918-
/* Fixed sense format */
919-
sb[0] |= 0x80;
920-
sb[3] = tf->error;
921-
sb[4] = tf->status;
922-
sb[5] = tf->device;
923-
sb[6] = tf->nsect;
924-
if (tf->flags & ATA_TFLAG_LBA48) {
925-
sb[8] |= 0x80;
926-
if (tf->hob_nsect)
927-
sb[8] |= 0x40;
928-
if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
929-
sb[8] |= 0x20;
930-
}
931-
sb[9] = tf->lbal;
932-
sb[10] = tf->lbam;
933-
sb[11] = tf->lbah;
934-
}
935950
}
936951

937952
/**
@@ -1632,26 +1647,32 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
16321647
{
16331648
struct scsi_cmnd *cmd = qc->scsicmd;
16341649
u8 *cdb = cmd->cmnd;
1635-
int need_sense = (qc->err_mask != 0) &&
1636-
!(qc->flags & ATA_QCFLAG_SENSE_VALID);
1650+
bool have_sense = qc->flags & ATA_QCFLAG_SENSE_VALID;
1651+
bool is_ata_passthru = cdb[0] == ATA_16 || cdb[0] == ATA_12;
1652+
bool is_ck_cond_request = cdb[2] & 0x20;
1653+
bool is_error = qc->err_mask != 0;
16371654

16381655
/* For ATA pass thru (SAT) commands, generate a sense block if
16391656
* user mandated it or if there's an error. Note that if we
1640-
* generate because the user forced us to [CK_COND =1], a check
1657+
* generate because the user forced us to [CK_COND=1], a check
16411658
* condition is generated and the ATA register values are returned
16421659
* whether the command completed successfully or not. If there
1643-
* was no error, we use the following sense data:
1660+
* was no error, and CK_COND=1, we use the following sense data:
16441661
* sk = RECOVERED ERROR
16451662
* asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE
16461663
*/
1647-
if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
1648-
((cdb[2] & 0x20) || need_sense))
1649-
ata_gen_passthru_sense(qc);
1650-
else if (need_sense)
1664+
if (is_ata_passthru && (is_ck_cond_request || is_error || have_sense)) {
1665+
if (!have_sense)
1666+
ata_gen_passthru_sense(qc);
1667+
ata_scsi_set_passthru_sense_fields(qc);
1668+
if (is_ck_cond_request)
1669+
set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION);
1670+
} else if (is_error && !have_sense) {
16511671
ata_gen_ata_sense(qc);
1652-
else
1672+
} else {
16531673
/* Keep the SCSI ML and status byte, clear host byte. */
16541674
cmd->result &= 0x0000ffff;
1675+
}
16551676

16561677
ata_qc_done(qc);
16571678
}
@@ -2590,14 +2611,8 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
25902611
/* handle completion from EH */
25912612
if (unlikely(err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID)) {
25922613

2593-
if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
2594-
/* FIXME: not quite right; we don't want the
2595-
* translation of taskfile registers into a
2596-
* sense descriptors, since that's only
2597-
* correct for ATA, not ATAPI
2598-
*/
2614+
if (!(qc->flags & ATA_QCFLAG_SENSE_VALID))
25992615
ata_gen_passthru_sense(qc);
2600-
}
26012616

26022617
/* SCSI EH automatically locks door if sdev->locked is
26032618
* set. Sometimes door lock request continues to

0 commit comments

Comments
 (0)