mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/9] libata sense code update
@ 2015-03-27 15:46 Hannes Reinecke
  2015-03-27 15:46 ` [PATCH 1/9] libata: use READ_LOG_DMA_EXT Hannes Reinecke
                   ` (9 more replies)
  0 siblings, 10 replies; 13+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

Hi all,

with ACS-4 ATA drives inherited the possibility to return
SCSI sense codes, allowing for a more precise error handling.
Not to mention a nice alignment with the SCSI error handling.
This patchset implements both, support for NCQ Autosense and
the sense data reporting feature set.
Plus some whitespace and assorted cleanups.
And I've added some tracepoints, too.

Hannes Reinecke (9):
  libata: use READ_LOG_DMA_EXT
  libata: whitespace cleanup in ata_get_cmd_descript()
  libata: whitespace fixes in ata_to_sense_error()
  ide,ata: Rename ATA_IDX to ATA_SENSE
  libata: use status bit definitions in ata_dump_status()
  libata: Implement NCQ autosense
  libata: Implement support for sense data reporting
  libata-eh: Set 'information' field for autosense
  libata: Add tracepoints

 drivers/ata/Makefile          |   3 +-
 drivers/ata/libata-core.c     |  32 ++++-
 drivers/ata/libata-eh.c       | 168 ++++++++++++++++++----
 drivers/ata/libata-scsi.c     | 111 ++++++++++-----
 drivers/ata/libata-trace.c    | 151 ++++++++++++++++++++
 drivers/ata/libata.h          |   6 +-
 drivers/ide/ide-lib.c         |   4 +-
 drivers/ide/ide-probe.c       |   2 +-
 drivers/scsi/scsi_error.c     |  31 ++++
 include/linux/ata.h           |  29 +++-
 include/scsi/scsi_eh.h        |   1 +
 include/trace/events/libata.h | 325 ++++++++++++++++++++++++++++++++++++++++++
 12 files changed, 786 insertions(+), 77 deletions(-)
 create mode 100644 drivers/ata/libata-trace.c
 create mode 100644 include/trace/events/libata.h

-- 
1.8.5.2


^ permalink raw reply	[flat|nested] 13+ messages in thread
* [PATCH 7/9] libata: Implement support for sense data reporting
@ 2015-03-27 15:48 Hannes Reinecke
  0 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:48 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

ACS-4 defines a sense data reporting feature set.
This patch implements support for it.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-core.c | 20 ++++++++++-
 drivers/ata/libata-eh.c   | 86 +++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/ata.h       | 18 ++++++++++
 3 files changed, 120 insertions(+), 4 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index ef150eb..2ff3ab6 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2144,6 +2144,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
@@ -2366,7 +2384,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 c9b1994..9fa81d9 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1618,6 +1618,70 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)
 }
 
 /**
+ *	ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT
+ *	@dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to
+ *	@sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
+ *	@dfl_sense_key: default sense key to use
+ *
+ *	Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK
+ *	SENSE.  This function is EH helper.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	encoded sense data on success, 0 on failure or if sense data
+ *	is not available.
+ */
+static u32 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 (!cmd)
+		return 0;
+
+	DPRINTK("ATA request sense\n");
+	ata_dev_warn(dev, "request sense\n");
+	if (!ata_id_sense_reporting_enabled(dev->id)) {
+		ata_dev_warn(qc->dev, "sense data reporting disabled\n");
+		return 0;
+	}
+	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);
+	/*
+	 * ACS-4 states:
+	 * The device may set the SENSE DATA AVAILABLE bit to one in the
+	 * STATUS field and clear the ERROR bit to zero in the STATUS field
+	 * to indicate that the command returned completion without an error
+	 * and the sense data described in table 306 is available.
+	 *
+	 * IOW the 'ATA_SENSE' bit might not be set even though valid
+	 * sense data is available.
+	 * So check for both.
+	 */
+	if ((tf.command & ATA_SENSE) ||
+		tf.lbah != 0 || tf.lbam != 0 || tf.lbal != 0) {
+		ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal);
+		qc->flags |= ATA_QCFLAG_SENSE_VALID;
+		ata_dev_warn(dev, "sense data %02x/%02x/%02x\n",
+			     tf.lbah, tf.lbam, tf.lbal);
+	} else {
+		ata_dev_warn(dev, "request sense failed stat %02x emask %x\n",
+			     tf.command, err_mask);
+	}
+	return err_mask;
+}
+
+/**
  *	atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
  *	@dev: device to perform REQUEST_SENSE to
  *	@sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
@@ -1820,7 +1884,22 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
 		return ATA_EH_RESET;
 	}
 
-	/* Set by NCQ autosense */
+	/*
+	 * Sense data reporting does not work if the
+	 * device fault bit is set.
+	 */
+	if ((stat & ATA_SENSE) && !(stat & ATA_DF) &&
+	    !(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
+		if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) {
+			tmp = ata_eh_request_sense(qc, qc->scsicmd);
+			if (tmp)
+				qc->err_mask |= tmp;
+		} else {
+			ata_dev_warn(qc->dev, "sense data available but port frozen\n");
+		}
+	}
+
+	/* Set by NCQ autosense or request sense above */
 	if (qc->flags & ATA_QCFLAG_SENSE_VALID)
 		return 0;
 
@@ -2566,14 +2645,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 0c65526..b666b77 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -94,6 +94,8 @@ enum {
 	ATA_ID_SECTOR_SIZE	= 106,
 	ATA_ID_WWN		= 108,
 	ATA_ID_LOGICAL_SECTOR_SIZE	= 117,	/* and 118 */
+	ATA_ID_COMMAND_SET_3	= 119,
+	ATA_ID_COMMAND_SET_4	= 120,
 	ATA_ID_LAST_LUN		= 126,
 	ATA_ID_DLF		= 128,
 	ATA_ID_CSFO		= 129,
@@ -382,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,
@@ -705,6 +709,20 @@ static inline bool ata_id_has_read_log_dma_ext(const u16 *id)
 	return id[ATA_ID_COMMAND_SET_3] & (1 << 3);
 }
 
+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
-- 
1.8.5.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-03-31 17:07 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
2015-03-27 15:46 ` [PATCH 1/9] libata: use READ_LOG_DMA_EXT Hannes Reinecke
2015-03-27 15:46 ` [PATCH 2/9] libata: whitespace cleanup in ata_get_cmd_descript() Hannes Reinecke
2015-03-27 15:46 ` [PATCH 3/9] libata: whitespace fixes in ata_to_sense_error() Hannes Reinecke
2015-03-27 15:46 ` [PATCH 4/9] ide,ata: Rename ATA_IDX to ATA_SENSE Hannes Reinecke
2015-03-31 17:07   ` David Miller
2015-03-27 15:46 ` [PATCH 5/9] libata: use status bit definitions in ata_dump_status() Hannes Reinecke
2015-03-27 15:46 ` [PATCH 6/9] libata: Implement NCQ autosense Hannes Reinecke
2015-03-27 15:46 ` [PATCH 7/9] libata: Implement support for sense data reporting Hannes Reinecke
2015-03-27 15:46 ` [PATCH 8/9] libata-eh: Set 'information' field for autosense Hannes Reinecke
2015-03-27 15:46 ` [PATCH 9/9] libata: Add tracepoints Hannes Reinecke
2015-03-27 16:01 ` [PATCH 0/9] libata sense code update Tejun Heo
2015-03-27 15:48 [PATCH 7/9] libata: Implement support for sense data reporting Hannes Reinecke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®