[Devel] [PATCH RHEL7 COMMIT] ms/libata: Implement support for sense data reporting
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Oct 1 17:49:56 MSK 2019
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 557b459f0af0be0488da745077fa98a7845c2a9f
Author: Hannes Reinecke <hare at suse.de>
Date: Tue Oct 1 17:49:54 2019 +0300
ms/libata: Implement support for sense data reporting
ACS-4 defines a sense data reporting feature set.
This patch implements support for it.
tj: Cosmetic formatting updates.
Signed-off-by: Hannes Reinecke <hare at suse.de>
Signed-off-by: Tejun Heo <tj at kernel.org>
https://pmc.acronis.com/browse/VSTOR-26930
(cherry picked from commit e87fd28cf9a2d9018ac4b6dd92f0b417714bc18d)
Signed-off-by: Ildar Ismagilov <ildar.ismagilov at 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-core.c | 20 +++++++++++++-
drivers/ata/libata-eh.c | 68 ++++++++++++++++++++++++++++++++++++++++++++---
include/linux/ata.h | 16 +++++++++++
3 files changed, 99 insertions(+), 5 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 913c677073d4..d2272247bf58 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2146,6 +2146,24 @@ static int ata_dev_config_ncq(struct ata_device *dev,
return 0;
}
+static void ata_dev_config_sense_reporting(struct ata_device *dev)
+{
+ unsigned int err_mask;
+
+ if (!ata_id_has_sense_reporting(dev->id))
+ return;
+
+ if (ata_id_sense_reporting_enabled(dev->id))
+ return;
+
+ err_mask = ata_dev_set_feature(dev, SETFEATURE_SENSE_DATA, 0x1);
+ if (err_mask) {
+ ata_dev_dbg(dev,
+ "failed to enable Sense Data Reporting, Emask 0x%x\n",
+ err_mask);
+ }
+}
+
/**
* ata_dev_configure - Configure the specified ATA/ATAPI device
* @dev: Target device to configure
@@ -2368,7 +2386,7 @@ int ata_dev_configure(struct ata_device *dev)
dev->devslp_timing[i] = sata_setting[j];
}
}
-
+ ata_dev_config_sense_reporting(dev);
dev->cdb_len = 16;
}
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index c055ec0c28d5..99c05bf9e071 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1642,6 +1642,56 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)
return err_mask;
}
+/**
+ * ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT
+ * @dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to
+ * @cmd: scsi command for which the sense code should be set
+ *
+ * Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK
+ * SENSE. This function is an EH helper.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+static void ata_eh_request_sense(struct ata_queued_cmd *qc,
+ struct scsi_cmnd *cmd)
+{
+ struct ata_device *dev = qc->dev;
+ struct ata_taskfile tf;
+ unsigned int err_mask;
+
+ if (qc->ap->pflags & ATA_PFLAG_FROZEN) {
+ ata_dev_warn(dev, "sense data available but port frozen\n");
+ return;
+ }
+
+ if (!cmd)
+ return;
+
+ if (!ata_id_sense_reporting_enabled(dev->id)) {
+ ata_dev_warn(qc->dev, "sense data reporting disabled\n");
+ return;
+ }
+
+ DPRINTK("ATA request sense\n");
+
+ ata_tf_init(dev, &tf);
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+ tf.command = ATA_CMD_REQ_SENSE_DATA;
+ tf.protocol = ATA_PROT_NODATA;
+
+ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+ /* Ignore err_mask; ATA_ERR might be set */
+ if (tf.command & ATA_SENSE) {
+ ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal);
+ qc->flags |= ATA_QCFLAG_SENSE_VALID;
+ } else {
+ ata_dev_warn(dev, "request sense failed stat %02x emask %x\n",
+ tf.command, err_mask);
+ }
+}
+
/**
* atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
* @dev: device to perform REQUEST_SENSE to
@@ -1843,14 +1893,23 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
return ATA_EH_RESET;
}
- if (stat & (ATA_ERR | ATA_DF))
+ if (stat & (ATA_ERR | ATA_DF)) {
qc->err_mask |= AC_ERR_DEV;
- else
+ /*
+ * Sense data reporting does not work if the
+ * device fault bit is set.
+ */
+ if (stat & ATA_DF)
+ stat &= ~ATA_SENSE;
+ } else {
return 0;
+ }
switch (qc->dev->class) {
case ATA_DEV_ATA:
case ATA_DEV_ZAC:
+ if (stat & ATA_SENSE)
+ ata_eh_request_sense(qc, qc->scsicmd);
if (err & ATA_ICRC)
qc->err_mask |= AC_ERR_ATA_BUS;
if (err & (ATA_UNC | ATA_AMNF))
@@ -2585,14 +2644,15 @@ static void ata_eh_link_report(struct ata_link *link)
#ifdef CONFIG_ATA_VERBOSE_ERROR
if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
- ATA_ERR)) {
+ ATA_SENSE | ATA_ERR)) {
if (res->command & ATA_BUSY)
ata_dev_err(qc->dev, "status: { Busy }\n");
else
- ata_dev_err(qc->dev, "status: { %s%s%s%s}\n",
+ ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n",
res->command & ATA_DRDY ? "DRDY " : "",
res->command & ATA_DF ? "DF " : "",
res->command & ATA_DRQ ? "DRQ " : "",
+ res->command & ATA_SENSE ? "SENSE " : "",
res->command & ATA_ERR ? "ERR " : "");
}
diff --git a/include/linux/ata.h b/include/linux/ata.h
index ffde13097ed1..78789b15eeae 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -384,6 +384,8 @@ enum {
SATA_SSP = 0x06, /* Software Settings Preservation */
SATA_DEVSLP = 0x09, /* Device Sleep */
+ SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */
+
/* feature values for SET_MAX */
ATA_SET_MAX_ADDR = 0x00,
ATA_SET_MAX_PASSWD = 0x01,
@@ -717,6 +719,20 @@ static inline bool ata_id_has_read_log_dma_ext(const u16 *id)
return false;
}
+static inline bool ata_id_has_sense_reporting(const u16 *id)
+{
+ if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
+ return false;
+ return id[ATA_ID_COMMAND_SET_3] & (1 << 6);
+}
+
+static inline bool ata_id_sense_reporting_enabled(const u16 *id)
+{
+ if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
+ return false;
+ return id[ATA_ID_COMMAND_SET_4] & (1 << 6);
+}
+
/**
* ata_id_major_version - get ATA level of drive
* @id: Identify data
More information about the Devel
mailing list