Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libata: don't request sense data on !ZAC ATA devices

ZAC support added sense data requesting on error for both ZAC and ATA
devices. This seems to cause erratic error handling behaviors on some
SSDs where the device reports sense data availability and then
delivers the wrong content making EH take the wrong actions. The
failure mode was sporadic on a LITE-ON ssd and couldn't be reliably
reproduced.

There is no value in requesting sense data from non-ZAC ATA devices
while there's a significant risk of introducing EH misbehaviors which
are difficult to reproduce and fix. Let's do the sense data dancing
only for ZAC devices.

Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Masato Suzuki <masato.suzuki@wdc.com>
Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Tejun Heo and committed by
Jens Axboe
ca156e00 9e0babf2

+5 -3
+5 -3
drivers/ata/libata-eh.c
··· 1469 1469 tf->hob_lbah = buf[10]; 1470 1470 tf->nsect = buf[12]; 1471 1471 tf->hob_nsect = buf[13]; 1472 - if (ata_id_has_ncq_autosense(dev->id)) 1472 + if (dev->class == ATA_DEV_ZAC && ata_id_has_ncq_autosense(dev->id)) 1473 1473 tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16]; 1474 1474 1475 1475 return 0; ··· 1716 1716 memcpy(&qc->result_tf, &tf, sizeof(tf)); 1717 1717 qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48; 1718 1718 qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; 1719 - if ((qc->result_tf.command & ATA_SENSE) || qc->result_tf.auxiliary) { 1719 + if (dev->class == ATA_DEV_ZAC && 1720 + ((qc->result_tf.command & ATA_SENSE) || qc->result_tf.auxiliary)) { 1720 1721 char sense_key, asc, ascq; 1721 1722 1722 1723 sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; ··· 1771 1770 } 1772 1771 1773 1772 switch (qc->dev->class) { 1774 - case ATA_DEV_ATA: 1775 1773 case ATA_DEV_ZAC: 1776 1774 if (stat & ATA_SENSE) 1777 1775 ata_eh_request_sense(qc, qc->scsicmd); 1776 + /* fall through */ 1777 + case ATA_DEV_ATA: 1778 1778 if (err & ATA_ICRC) 1779 1779 qc->err_mask |= AC_ERR_ATA_BUS; 1780 1780 if (err & (ATA_UNC | ATA_AMNF))