[RHEL7,COMMIT] ms/libata: Implement NCQ autosense

Submitted by Konstantin Khorenko on Oct. 1, 2019, 2:49 p.m.

Details

Message ID 201910011449.x91Enrfg015537@finist-ce7.sw.ru
State New
Series "ms/libata: Implement NCQ autosense"
Headers show

Commit Message

Konstantin Khorenko Oct. 1, 2019, 2:49 p.m.
The commit is pushed to "branch-rh7-3.10.0-957.27.2.vz7.107.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.27.2.vz7.107.11
------>
commit c9ca61b3aacf972ffe982e7d811c058a1a38312d
Author: Hannes Reinecke <hare@suse.de>
Date:   Tue Oct 1 17:49:53 2019 +0300

    ms/libata: Implement NCQ autosense
    
    Some newer devices support NCQ autosense (cf ACS-4), so we should
    be using it to retrieve the sense code and speed up recovery.
    
    Signed-off-by: Hannes Reinecke <hare@suse.de>
    Signed-off-by: Tejun Heo <tj@kernel.org>
    
    https://pmc.acronis.com/browse/VSTOR-26930
    (cherry picked from commit 5b01e4b9efa0b78672cbbea830c9fbcc7f239e29)
    Signed-off-by: Ildar Ismagilov <ildar.ismagilov@virtuozzo.com>
    
    =====================
    Patchset description:
    
    Add support of SMR ATA disk
    
    This patchset adds support of SMR ATA disk through SCSI generic interface
    aka /dev/sgX.
    
    The SCSI generic interface is used by libzbc library for communicate
    with SMR disk. These patches allow us to use SMR disk through
    "ata" backend of libzbc ("scsi" and "block" backends aren't supported).
    
    These patches were tested with following command:
     libzbc/test/zbc_test.sh /dev/sgX
    
    JIRA: https://pmc.acronis.com/browse/VSTOR-26930
    
    Damien Le Moal (1):
      libata: Fix ATA request sense
    
    Hannes Reinecke (5):
      libata: Implement ATA_DEV_ZAC
      libata-scsi: Update SATL for ZAC drives
      libata: Implement NCQ autosense
      libata: Implement support for sense data reporting
      libata: fixup ZAC device disabling
---
 drivers/ata/libata-eh.c   | 12 ++++++++++++
 drivers/ata/libata-scsi.c |  7 ++++++-
 drivers/ata/libata.h      |  1 +
 include/linux/ata.h       |  2 ++
 4 files changed, 21 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index e52e2758075a..c055ec0c28d5 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1605,6 +1605,8 @@  static int ata_eh_read_log_10h(struct ata_device *dev,
 	tf->hob_lbah = buf[10];
 	tf->nsect = buf[12];
 	tf->hob_nsect = buf[13];
+	if (ata_id_has_ncq_autosense(dev->id))
+		tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16];
 
 	return 0;
 }
@@ -1802,6 +1804,16 @@  void ata_eh_analyze_ncq_error(struct ata_link *link)
 	memcpy(&qc->result_tf, &tf, sizeof(tf));
 	qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
 	qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
+	if (qc->result_tf.auxiliary) {
+		char sense_key, asc, ascq;
+
+		sense_key = (qc->result_tf.auxiliary >> 16) & 0xff;
+		asc = (qc->result_tf.auxiliary >> 8) & 0xff;
+		ascq = qc->result_tf.auxiliary & 0xff;
+		ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq);
+		qc->flags |= ATA_QCFLAG_SENSE_VALID;
+	}
+
 	ehc->i.err_mask &= ~AC_ERR_DEV;
 }
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 8d907c11c3c9..23311363e1f8 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -269,8 +269,11 @@  DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR,
 	    ata_scsi_park_show, ata_scsi_park_store);
 EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
 
-static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
 {
+	if (!cmd)
+		return;
+
 	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
 	scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
@@ -1785,6 +1788,8 @@  static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 	if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
 	    ((cdb[2] & 0x20) || need_sense))
 		ata_gen_passthru_sense(qc);
+	else if (qc->flags & ATA_QCFLAG_SENSE_VALID)
+		cmd->result = SAM_STAT_CHECK_CONDITION;
 	else if (need_sense)
 		ata_gen_ata_sense(qc);
 	else
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index a569b205635c..162f98eb3799 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -137,6 +137,7 @@  extern int ata_scsi_add_hosts(struct ata_host *host,
 			      struct scsi_host_template *sht);
 extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
 extern int ata_scsi_offline_dev(struct ata_device *dev);
+extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq);
 extern void ata_scsi_media_change_notify(struct ata_device *dev);
 extern void ata_scsi_hotplug(struct work_struct *work);
 extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 832257f6e6d9..ffde13097ed1 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -527,6 +527,8 @@  struct ata_bmdma_prd {
 #define ata_id_cdb_intr(id)	(((id)[ATA_ID_CONFIG] & 0x60) == 0x20)
 #define ata_id_has_da(id)	((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4))
 #define ata_id_has_devslp(id)	((id)[ATA_ID_FEATURE_SUPP] & (1 << 8))
+#define ata_id_has_ncq_autosense(id) \
+				((id)[ATA_ID_FEATURE_SUPP] & (1 << 7))
 
 static inline bool ata_id_has_hipm(const u16 *id)
 {