linux-ide.vger.kernel.org archive mirror
 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; 12+ 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] 12+ messages in thread

* [PATCH 1/9] libata: use READ_LOG_DMA_EXT
  2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
@ 2015-03-27 15:46 ` Hannes Reinecke
  2015-03-27 15:46 ` [PATCH 2/9] libata: whitespace cleanup in ata_get_cmd_descript() Hannes Reinecke
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

If READ_LOG_DMA_EXT is supported we should try to use it for
reading the log pages.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-eh.c | 9 +++++++--
 include/linux/ata.h     | 7 +++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index d2029a4..d35d7a7 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1510,13 +1510,18 @@ unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
 	DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
 
 	ata_tf_init(dev, &tf);
-	tf.command = ATA_CMD_READ_LOG_EXT;
+	if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id)) {
+		tf.command = ATA_CMD_READ_LOG_DMA_EXT;
+		tf.protocol = ATA_PROT_DMA;
+	} else {
+		tf.command = ATA_CMD_READ_LOG_EXT;
+		tf.protocol = ATA_PROT_PIO;
+	}
 	tf.lbal = log;
 	tf.lbam = page;
 	tf.nsect = sectors;
 	tf.hob_nsect = sectors >> 8;
 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
-	tf.protocol = ATA_PROT_PIO;
 
 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
 				     buf, sectors * ATA_SECT_SIZE, 0);
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 1648026..681520f 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -696,6 +696,13 @@ static inline bool ata_id_wcache_enabled(const u16 *id)
 	return id[ATA_ID_CFS_ENABLE_1] & (1 << 5);
 }
 
+static inline bool ata_id_has_read_log_dma_ext(const u16 *id)
+{
+	if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
+		return false;
+	return id[ATA_ID_COMMAND_SET_3] & (1 << 3);
+}
+
 /**
  *	ata_id_major_version	-	get ATA level of drive
  *	@id: Identify data
-- 
1.8.5.2


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

* [PATCH 2/9] libata: whitespace cleanup in ata_get_cmd_descript()
  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 ` Hannes Reinecke
  2015-03-27 15:46 ` [PATCH 3/9] libata: whitespace fixes in ata_to_sense_error() Hannes Reinecke
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-eh.c | 50 ++++++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index d35d7a7..50ffd4e 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2294,27 +2294,27 @@ const char *ata_get_cmd_descript(u8 command)
 		const char *text;
 	} cmd_descr[] = {
 		{ ATA_CMD_DEV_RESET,		"DEVICE RESET" },
-		{ ATA_CMD_CHK_POWER, 		"CHECK POWER MODE" },
-		{ ATA_CMD_STANDBY, 		"STANDBY" },
-		{ ATA_CMD_IDLE, 		"IDLE" },
-		{ ATA_CMD_EDD, 			"EXECUTE DEVICE DIAGNOSTIC" },
-		{ ATA_CMD_DOWNLOAD_MICRO,   	"DOWNLOAD MICROCODE" },
+		{ ATA_CMD_CHK_POWER,		"CHECK POWER MODE" },
+		{ ATA_CMD_STANDBY,		"STANDBY" },
+		{ ATA_CMD_IDLE,			"IDLE" },
+		{ ATA_CMD_EDD,			"EXECUTE DEVICE DIAGNOSTIC" },
+		{ ATA_CMD_DOWNLOAD_MICRO,	"DOWNLOAD MICROCODE" },
 		{ ATA_CMD_DOWNLOAD_MICRO_DMA,	"DOWNLOAD MICROCODE DMA" },
 		{ ATA_CMD_NOP,			"NOP" },
-		{ ATA_CMD_FLUSH, 		"FLUSH CACHE" },
-		{ ATA_CMD_FLUSH_EXT, 		"FLUSH CACHE EXT" },
-		{ ATA_CMD_ID_ATA,  		"IDENTIFY DEVICE" },
-		{ ATA_CMD_ID_ATAPI, 		"IDENTIFY PACKET DEVICE" },
-		{ ATA_CMD_SERVICE, 		"SERVICE" },
-		{ ATA_CMD_READ, 		"READ DMA" },
-		{ ATA_CMD_READ_EXT, 		"READ DMA EXT" },
-		{ ATA_CMD_READ_QUEUED, 		"READ DMA QUEUED" },
-		{ ATA_CMD_READ_STREAM_EXT, 	"READ STREAM EXT" },
+		{ ATA_CMD_FLUSH,		"FLUSH CACHE" },
+		{ ATA_CMD_FLUSH_EXT,		"FLUSH CACHE EXT" },
+		{ ATA_CMD_ID_ATA,		"IDENTIFY DEVICE" },
+		{ ATA_CMD_ID_ATAPI,		"IDENTIFY PACKET DEVICE" },
+		{ ATA_CMD_SERVICE,		"SERVICE" },
+		{ ATA_CMD_READ,			"READ DMA" },
+		{ ATA_CMD_READ_EXT,		"READ DMA EXT" },
+		{ ATA_CMD_READ_QUEUED,		"READ DMA QUEUED" },
+		{ ATA_CMD_READ_STREAM_EXT,	"READ STREAM EXT" },
 		{ ATA_CMD_READ_STREAM_DMA_EXT,  "READ STREAM DMA EXT" },
-		{ ATA_CMD_WRITE, 		"WRITE DMA" },
-		{ ATA_CMD_WRITE_EXT, 		"WRITE DMA EXT" },
-		{ ATA_CMD_WRITE_QUEUED, 	"WRITE DMA QUEUED EXT" },
-		{ ATA_CMD_WRITE_STREAM_EXT, 	"WRITE STREAM EXT" },
+		{ ATA_CMD_WRITE,		"WRITE DMA" },
+		{ ATA_CMD_WRITE_EXT,		"WRITE DMA EXT" },
+		{ ATA_CMD_WRITE_QUEUED,		"WRITE DMA QUEUED EXT" },
+		{ ATA_CMD_WRITE_STREAM_EXT,	"WRITE STREAM EXT" },
 		{ ATA_CMD_WRITE_STREAM_DMA_EXT, "WRITE STREAM DMA EXT" },
 		{ ATA_CMD_WRITE_FUA_EXT,	"WRITE DMA FUA EXT" },
 		{ ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" },
@@ -2330,7 +2330,7 @@ const char *ata_get_cmd_descript(u8 command)
 		{ ATA_CMD_READ_MULTI_EXT,	"READ MULTIPLE EXT" },
 		{ ATA_CMD_WRITE_MULTI,		"WRITE MULTIPLE" },
 		{ ATA_CMD_WRITE_MULTI_EXT,	"WRITE MULTIPLE EXT" },
-		{ ATA_CMD_WRITE_MULTI_FUA_EXT, 	"WRITE MULTIPLE FUA EXT" },
+		{ ATA_CMD_WRITE_MULTI_FUA_EXT,	"WRITE MULTIPLE FUA EXT" },
 		{ ATA_CMD_SET_FEATURES,		"SET FEATURES" },
 		{ ATA_CMD_SET_MULTI,		"SET MULTIPLE MODE" },
 		{ ATA_CMD_VERIFY,		"READ VERIFY SECTOR(S)" },
@@ -2347,12 +2347,12 @@ const char *ata_get_cmd_descript(u8 command)
 		{ ATA_CMD_READ_LOG_EXT,		"READ LOG EXT" },
 		{ ATA_CMD_WRITE_LOG_EXT,	"WRITE LOG EXT" },
 		{ ATA_CMD_READ_LOG_DMA_EXT,	"READ LOG DMA EXT" },
-		{ ATA_CMD_WRITE_LOG_DMA_EXT, 	"WRITE LOG DMA EXT" },
+		{ ATA_CMD_WRITE_LOG_DMA_EXT,	"WRITE LOG DMA EXT" },
 		{ ATA_CMD_TRUSTED_NONDATA,	"TRUSTED NON-DATA" },
 		{ ATA_CMD_TRUSTED_RCV,		"TRUSTED RECEIVE" },
-		{ ATA_CMD_TRUSTED_RCV_DMA, 	"TRUSTED RECEIVE DMA" },
+		{ ATA_CMD_TRUSTED_RCV_DMA,	"TRUSTED RECEIVE DMA" },
 		{ ATA_CMD_TRUSTED_SND,		"TRUSTED SEND" },
-		{ ATA_CMD_TRUSTED_SND_DMA, 	"TRUSTED SEND DMA" },
+		{ ATA_CMD_TRUSTED_SND_DMA,	"TRUSTED SEND DMA" },
 		{ ATA_CMD_PMP_READ,		"READ BUFFER" },
 		{ ATA_CMD_PMP_READ_DMA,		"READ BUFFER DMA" },
 		{ ATA_CMD_PMP_WRITE,		"WRITE BUFFER" },
@@ -2369,12 +2369,12 @@ const char *ata_get_cmd_descript(u8 command)
 		{ ATA_CMD_MEDIA_LOCK,		"DOOR LOCK" },
 		{ ATA_CMD_MEDIA_UNLOCK,		"DOOR UNLOCK" },
 		{ ATA_CMD_DSM,			"DATA SET MANAGEMENT" },
-		{ ATA_CMD_CHK_MED_CRD_TYP, 	"CHECK MEDIA CARD TYPE" },
-		{ ATA_CMD_CFA_REQ_EXT_ERR, 	"CFA REQUEST EXTENDED ERROR" },
+		{ ATA_CMD_CHK_MED_CRD_TYP,	"CHECK MEDIA CARD TYPE" },
+		{ ATA_CMD_CFA_REQ_EXT_ERR,	"CFA REQUEST EXTENDED ERROR" },
 		{ ATA_CMD_CFA_WRITE_NE,		"CFA WRITE SECTORS WITHOUT ERASE" },
 		{ ATA_CMD_CFA_TRANS_SECT,	"CFA TRANSLATE SECTOR" },
 		{ ATA_CMD_CFA_ERASE,		"CFA ERASE SECTORS" },
-		{ ATA_CMD_CFA_WRITE_MULT_NE, 	"CFA WRITE MULTIPLE WITHOUT ERASE" },
+		{ ATA_CMD_CFA_WRITE_MULT_NE,	"CFA WRITE MULTIPLE WITHOUT ERASE" },
 		{ ATA_CMD_REQ_SENSE_DATA,	"REQUEST SENSE DATA EXT" },
 		{ ATA_CMD_SANITIZE_DEVICE,	"SANITIZE DEVICE" },
 		{ ATA_CMD_READ_LONG,		"READ LONG (with retries)" },
-- 
1.8.5.2


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

* [PATCH 3/9] libata: whitespace fixes in ata_to_sense_error()
  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 ` Hannes Reinecke
  2015-03-27 15:46 ` [PATCH 4/9] ide,ata: Rename ATA_IDX to ATA_SENSE Hannes Reinecke
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-scsi.c | 61 +++++++++++++++++++++++++++++++----------------
 1 file changed, 40 insertions(+), 21 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b061ba2..d2b6196 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -849,40 +849,59 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
 	/* Based on the 3ware driver translation table */
 	static const unsigned char sense_table[][4] = {
 		/* BBD|ECC|ID|MAR */
-		{0xd1, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
+		{0xd1,		ABORTED_COMMAND, 0x00, 0x00},
+			// Device busy                  Aborted command
 		/* BBD|ECC|ID */
-		{0xd0,  	ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
+		{0xd0,		ABORTED_COMMAND, 0x00, 0x00},
+			// Device busy                  Aborted command
 		/* ECC|MC|MARK */
-		{0x61, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Device fault                 Hardware error
+		{0x61,		HARDWARE_ERROR, 0x00, 0x00},
+			// Device fault                 Hardware error
 		/* ICRC|ABRT */		/* NB: ICRC & !ABRT is BBD */
-		{0x84, 		ABORTED_COMMAND, 0x47, 0x00}, 	// Data CRC error               SCSI parity error
+		{0x84,		ABORTED_COMMAND, 0x47, 0x00},
+			// Data CRC error               SCSI parity error
 		/* MC|ID|ABRT|TRK0|MARK */
-		{0x37, 		NOT_READY, 0x04, 0x00}, 	// Unit offline                 Not ready
+		{0x37,		NOT_READY, 0x04, 0x00},
+			// Unit offline                 Not ready
 		/* MCR|MARK */
-		{0x09, 		NOT_READY, 0x04, 0x00}, 	// Unrecovered disk error       Not ready
+		{0x09,		NOT_READY, 0x04, 0x00},
+			// Unrecovered disk error       Not ready
 		/*  Bad address mark */
-		{0x01, 		MEDIUM_ERROR, 0x13, 0x00}, 	// Address mark not found       Address mark not found for data field
-		/* TRK0 */
-		{0x02, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Track 0 not found		Hardware error
+		{0x01,		MEDIUM_ERROR, 0x13, 0x00},
+			// Address mark not found for data field
+		/* TRK0 - Track 0 not found */
+		{0x02,		HARDWARE_ERROR, 0x00, 0x00},
+			// Hardware error
 		/* Abort: 0x04 is not translated here, see below */
 		/* Media change request */
-		{0x08, 		NOT_READY, 0x04, 0x00}, 	// Media change request	  FIXME: faking offline
-		/* SRV/IDNF */
-		{0x10, 		ILLEGAL_REQUEST, 0x21, 0x00}, 	// ID not found                 Logical address out of range
-		/* MC */
-		{0x20, 		UNIT_ATTENTION, 0x28, 0x00}, 	// Media Changed		Not ready to ready change, medium may have changed
-		/* ECC */
-		{0x40, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Uncorrectable ECC error      Unrecovered read error
+		{0x08,		NOT_READY, 0x04, 0x00},
+			// FIXME: faking offline
+		/* SRV/IDNF - ID not found */
+		{0x10,		ILLEGAL_REQUEST, 0x21, 0x00},
+			// Logical address out of range
+		/* MC - Media Changed */
+		{0x20,		UNIT_ATTENTION, 0x28, 0x00},
+			// Not ready to ready change, medium may have changed
+		/* ECC - Uncorrectable ECC error */
+		{0x40,		MEDIUM_ERROR, 0x11, 0x04},
+			// Unrecovered read error
 		/* BBD - block marked bad */
-		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		Medium error, unrecovered read error
+		{0x80,		MEDIUM_ERROR, 0x11, 0x04},
+			// Block marked bad	Medium error, unrecovered read error
 		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
 	};
 	static const unsigned char stat_table[][4] = {
 		/* Must be first because BUSY means no other bits valid */
-		{0x80, 		ABORTED_COMMAND, 0x47, 0x00},	// Busy, fake parity for now
-		{0x20, 		HARDWARE_ERROR,  0x44, 0x00}, 	// Device fault, internal target failure
-		{0x08, 		ABORTED_COMMAND, 0x47, 0x00},	// Timed out in xfer, fake parity for now
-		{0x04, 		RECOVERED_ERROR, 0x11, 0x00},	// Recovered ECC error	  Medium error, recovered
+		{0x80,		ABORTED_COMMAND, 0x47, 0x00},
+		// Busy, fake parity for now
+		{0x40,		ILLEGAL_REQUEST, 0x21, 0x04},
+		// Device ready, unaligned write command
+		{0x20,		HARDWARE_ERROR,  0x44, 0x00},
+		// Device fault, internal target failure
+		{0x08,		ABORTED_COMMAND, 0x47, 0x00},
+		// Timed out in xfer, fake parity for now
+		{0x04,		RECOVERED_ERROR, 0x11, 0x00},
+		// Recovered ECC error	  Medium error, recovered
 		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
 	};
 
-- 
1.8.5.2

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

* [PATCH 4/9] ide,ata: Rename ATA_IDX to ATA_SENSE
  2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
                   ` (2 preceding siblings ...)
  2015-03-27 15:46 ` [PATCH 3/9] libata: whitespace fixes in ata_to_sense_error() Hannes Reinecke
@ 2015-03-27 15:46 ` 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
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

ATA-8 defines bit 1 as 'ATA_SENSE', not 'ATA_IDX'.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-scsi.c | 2 +-
 drivers/ide/ide-lib.c     | 4 ++--
 drivers/ide/ide-probe.c   | 2 +-
 include/linux/ata.h       | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d2b6196..1f1cb69 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -804,7 +804,7 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
 		if (stat & 0x10)	printk("SeekComplete ");
 		if (stat & 0x08)	printk("DataRequest ");
 		if (stat & 0x04)	printk("CorrectedError ");
-		if (stat & 0x02)	printk("Index ");
+		if (stat & 0x02)	printk("Sense ");
 		if (stat & 0x01)	printk("Error ");
 		printk("}\n");
 
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index d9c9829..e1180fa 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -148,8 +148,8 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
 			printk(KERN_CONT "DataRequest ");
 		if (stat & ATA_CORR)
 			printk(KERN_CONT "CorrectedError ");
-		if (stat & ATA_IDX)
-			printk(KERN_CONT "Index ");
+		if (stat & ATA_SENSE)
+			printk(KERN_CONT "Sense ");
 		if (stat & ATA_ERR)
 			printk(KERN_CONT "Error ");
 	}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index a3d3b17..0b63fac 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -273,7 +273,7 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id, int irq_ctx)
 	    (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) {
 		a = tp_ops->read_altstatus(hwif);
 		s = tp_ops->read_status(hwif);
-		if ((a ^ s) & ~ATA_IDX)
+		if ((a ^ s) & ~ATA_SENSE)
 			/* ancient Seagate drives, broken interfaces */
 			printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
 					 "instead of ALTSTATUS(0x%02x)\n",
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 681520f..e3cb41c 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -177,7 +177,7 @@ enum {
 	ATA_DSC			= (1 << 4),	/* drive seek complete */
 	ATA_DRQ			= (1 << 3),	/* data request i/o */
 	ATA_CORR		= (1 << 2),	/* corrected data error */
-	ATA_IDX			= (1 << 1),	/* index */
+	ATA_SENSE		= (1 << 1),	/* sense code available */
 	ATA_ERR			= (1 << 0),	/* have an error */
 	ATA_SRST		= (1 << 2),	/* software reset */
 	ATA_ICRC		= (1 << 7),	/* interface CRC error */
-- 
1.8.5.2


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

* [PATCH 5/9] libata: use status bit definitions in ata_dump_status()
  2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
                   ` (3 preceding siblings ...)
  2015-03-27 15:46 ` [PATCH 4/9] ide,ata: Rename ATA_IDX to ATA_SENSE Hannes Reinecke
@ 2015-03-27 15:46 ` Hannes Reinecke
  2015-03-27 15:46 ` [PATCH 6/9] libata: Implement NCQ autosense Hannes Reinecke
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

Use the bit definitions for better readability.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-scsi.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 1f1cb69..f065cb1 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -799,26 +799,27 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
 	if (stat & ATA_BUSY) {
 		printk("Busy }\n");	/* Data is not valid in this case */
 	} else {
-		if (stat & 0x40)	printk("DriveReady ");
-		if (stat & 0x20)	printk("DeviceFault ");
-		if (stat & 0x10)	printk("SeekComplete ");
-		if (stat & 0x08)	printk("DataRequest ");
-		if (stat & 0x04)	printk("CorrectedError ");
-		if (stat & 0x02)	printk("Sense ");
-		if (stat & 0x01)	printk("Error ");
+		if (stat & ATA_DRDY)	printk("DriveReady ");
+		if (stat & ATA_DF)	printk("DeviceFault ");
+		if (stat & ATA_DSC)	printk("SeekComplete ");
+		if (stat & ATA_DRQ)	printk("DataRequest ");
+		if (stat & ATA_CORR)	printk("CorrectedError ");
+		if (stat & ATA_SENSE)	printk("Sense ");
+		if (stat & ATA_ERR)	printk("Error ");
 		printk("}\n");
 
 		if (err) {
 			printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
-			if (err & 0x04)		printk("DriveStatusError ");
-			if (err & 0x80) {
-				if (err & 0x04)	printk("BadCRC ");
+			if (err & ATA_ABORTED)	printk("DriveStatusError ");
+			if (err & ATA_ICRC) {
+				if (err & ATA_ABORTED)
+						printk("BadCRC ");
 				else		printk("Sector ");
 			}
-			if (err & 0x40)		printk("UncorrectableError ");
-			if (err & 0x10)		printk("SectorIdNotFound ");
-			if (err & 0x02)		printk("TrackZeroNotFound ");
-			if (err & 0x01)		printk("AddrMarkNotFound ");
+			if (err & ATA_UNC)	printk("UncorrectableError ");
+			if (err & ATA_IDNF)	printk("SectorIdNotFound ");
+			if (err & ATA_TRK0NF)	printk("TrackZeroNotFound ");
+			if (err & ATA_AMNF)	printk("AddrMarkNotFound ");
 			printk("}\n");
 		}
 	}
-- 
1.8.5.2


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

* [PATCH 6/9] libata: Implement NCQ autosense
  2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
                   ` (4 preceding siblings ...)
  2015-03-27 15:46 ` [PATCH 5/9] libata: use status bit definitions in ata_dump_status() Hannes Reinecke
@ 2015-03-27 15:46 ` Hannes Reinecke
  2015-03-27 15:46 ` [PATCH 7/9] libata: Implement support for sense data reporting Hannes Reinecke
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

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>
---
 drivers/ata/libata-eh.c   | 18 ++++++++++++++++++
 drivers/ata/libata-scsi.c |  9 +++++++--
 drivers/ata/libata.h      |  1 +
 include/linux/ata.h       |  2 ++
 4 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 50ffd4e..c9b1994 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1580,6 +1580,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;
 }
@@ -1777,6 +1779,18 @@ 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_dev_dbg(dev, "NCQ Autosense %02x/%02x/%02x\n",
+			    sense_key, asc, ascq);
+		ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq);
+		qc->flags |= ATA_QCFLAG_SENSE_VALID;
+	}
+
 	ehc->i.err_mask &= ~AC_ERR_DEV;
 }
 
@@ -1806,6 +1820,10 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
 		return ATA_EH_RESET;
 	}
 
+	/* Set by NCQ autosense */
+	if (qc->flags & ATA_QCFLAG_SENSE_VALID)
+		return 0;
+
 	if (stat & (ATA_ERR | ATA_DF))
 		qc->err_mask |= AC_ERR_DEV;
 	else
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index f065cb1..2e126c1 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -270,8 +270,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);
@@ -1777,7 +1780,9 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 	    ((cdb[2] & 0x20) || need_sense)) {
 		ata_gen_passthru_sense(qc);
 	} else {
-		if (!need_sense) {
+		if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+			cmd->result = SAM_STAT_CHECK_CONDITION;
+		} else if (!need_sense) {
 			cmd->result = SAM_STAT_GOOD;
 		} else {
 			/* TODO: decide which descriptor format to use
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index f840ca1..8cfdd96 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 e3cb41c..0c65526 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -525,6 +525,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)
 {
-- 
1.8.5.2

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

* [PATCH 7/9] libata: Implement support for sense data reporting
  2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
                   ` (5 preceding siblings ...)
  2015-03-27 15:46 ` [PATCH 6/9] libata: Implement NCQ autosense Hannes Reinecke
@ 2015-03-27 15:46 ` Hannes Reinecke
  2015-03-27 15:46 ` [PATCH 8/9] libata-eh: Set 'information' field for autosense Hannes Reinecke
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 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 related	[flat|nested] 12+ messages in thread

* [PATCH 8/9] libata-eh: Set 'information' field for autosense
  2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
                   ` (6 preceding siblings ...)
  2015-03-27 15:46 ` [PATCH 7/9] libata: Implement support for sense data reporting Hannes Reinecke
@ 2015-03-27 15:46 ` 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
  9 siblings, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

If NCQ autosense or the sense data reporting feature is enabled
the LBA of the offending command should be stored in the sense
data 'information' field.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-core.c |  4 ++--
 drivers/ata/libata-eh.c   |  3 +++
 drivers/ata/libata-scsi.c | 12 ++++++++++++
 drivers/ata/libata.h      |  5 ++++-
 drivers/scsi/scsi_error.c | 31 +++++++++++++++++++++++++++++++
 include/scsi/scsi_eh.h    |  1 +
 6 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2ff3ab6..51cba76 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -691,11 +691,11 @@ static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev)
  *	RETURNS:
  *	Block address read from @tf.
  */
-u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
+u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
 {
 	u64 block = 0;
 
-	if (tf->flags & ATA_TFLAG_LBA) {
+	if (!dev || tf->flags & ATA_TFLAG_LBA) {
 		if (tf->flags & ATA_TFLAG_LBA48) {
 			block |= (u64)tf->hob_lbah << 40;
 			block |= (u64)tf->hob_lbam << 32;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 9fa81d9..77ef43e 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1852,6 +1852,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
 		ata_dev_dbg(dev, "NCQ Autosense %02x/%02x/%02x\n",
 			    sense_key, asc, ascq);
 		ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq);
+		ata_scsi_set_sense_information(qc->scsicmd, &qc->result_tf);
 		qc->flags |= ATA_QCFLAG_SENSE_VALID;
 	}
 
@@ -1894,6 +1895,8 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
 			tmp = ata_eh_request_sense(qc, qc->scsicmd);
 			if (tmp)
 				qc->err_mask |= tmp;
+			else
+				ata_scsi_set_sense_information(qc->scsicmd, tf);
 		} else {
 			ata_dev_warn(qc->dev, "sense data available but port frozen\n");
 		}
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 2e126c1..35fec70 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -280,6 +280,18 @@ void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
 	scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
 }
 
+void ata_scsi_set_sense_information(struct scsi_cmnd *cmd,
+				    const struct ata_taskfile *tf)
+{
+	u64 information;
+
+	if (!cmd)
+		return;
+
+	information = ata_tf_read_block(tf, NULL);
+	scsi_set_sense_information(cmd->sense_buffer, information);
+}
+
 static ssize_t
 ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 8cfdd96..a998a17 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -67,7 +67,8 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag);
 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
 			   u64 block, u32 n_block, unsigned int tf_flags,
 			   unsigned int tag);
-extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
+extern u64 ata_tf_read_block(const struct ata_taskfile *tf,
+			     struct ata_device *dev);
 extern unsigned ata_exec_internal(struct ata_device *dev,
 				  struct ata_taskfile *tf, const u8 *cdb,
 				  int dma_dir, void *buf, unsigned int buflen,
@@ -138,6 +139,8 @@ extern int ata_scsi_add_hosts(struct ata_host *host,
 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_set_sense_information(struct scsi_cmnd *cmd,
+					   const struct ata_taskfile *tf);
 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/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 4cdaffc..c95a4e9 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -26,6 +26,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
+#include <asm/unaligned.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -2586,3 +2587,33 @@ void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
 	}
 }
 EXPORT_SYMBOL(scsi_build_sense_buffer);
+
+/**
+ * scsi_set_sense_information - set the information field in a
+ *		formatted sense data buffer
+ * @buf:	Where to build sense data
+ * @info:	64-bit information value to be set
+ *
+ **/
+void scsi_set_sense_information(u8 *buf, u64 info)
+{
+	if ((buf[0] & 0x7f) == 0x72) {
+		u8 *ucp, len;
+
+		len = buf[7];
+		ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0);
+		if (!ucp) {
+			buf[7] = len + 0xa;
+			ucp = buf + 8 + len;
+		}
+		ucp[0] = 0;
+		ucp[1] = 0xa;
+		ucp[2] = 0x80; /* Valid bit */
+		ucp[3] = 0;
+		put_unaligned_be64(info, &ucp[4]);
+	} else if ((buf[0] & 0x7f) == 0x70) {
+		buf[0] |= 0x80;
+		put_unaligned_be64(info, &buf[3]);
+	}
+}
+EXPORT_SYMBOL(scsi_set_sense_information);
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 1e1421b..5a4bb5b 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -59,6 +59,7 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
 				   u64 * info_out);
 
 extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
+extern void scsi_set_sense_information(u8 *buf, u64 info);
 
 extern int scsi_ioctl_reset(struct scsi_device *, int __user *);
 
-- 
1.8.5.2

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

* [PATCH 9/9] libata: Add tracepoints
  2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
                   ` (7 preceding siblings ...)
  2015-03-27 15:46 ` [PATCH 8/9] libata-eh: Set 'information' field for autosense Hannes Reinecke
@ 2015-03-27 15:46 ` Hannes Reinecke
  2015-03-27 16:01 ` [PATCH 0/9] libata sense code update Tejun Heo
  9 siblings, 0 replies; 12+ messages in thread
From: Hannes Reinecke @ 2015-03-27 15:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide, linux-kernel, Hannes Reinecke

Add some tracepoints for ata_qc_issue, ata_qc_complete, and
ata_eh_link_autopsy.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/Makefile          |   3 +-
 drivers/ata/libata-core.c     |   8 +-
 drivers/ata/libata-eh.c       |   4 +-
 drivers/ata/libata-trace.c    | 151 ++++++++++++++++++++
 include/trace/events/libata.h | 325 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 488 insertions(+), 3 deletions(-)
 create mode 100644 drivers/ata/libata-trace.c
 create mode 100644 include/trace/events/libata.h

diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index ae41107..b67e995 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -111,7 +111,8 @@ obj-$(CONFIG_ATA_GENERIC)	+= ata_generic.o
 # Should be last libata driver
 obj-$(CONFIG_PATA_LEGACY)	+= pata_legacy.o
 
-libata-y	:= libata-core.o libata-scsi.o libata-eh.o libata-transport.o
+libata-y	:= libata-core.o libata-scsi.o libata-eh.o \
+	libata-transport.o libata-trace.o
 libata-$(CONFIG_ATA_SFF)	+= libata-sff.o
 libata-$(CONFIG_SATA_PMP)	+= libata-pmp.o
 libata-$(CONFIG_ATA_ACPI)	+= libata-acpi.o
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 51cba76..1882fd2 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -70,6 +70,9 @@
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/libata.h>
+
 #include "libata.h"
 #include "libata-transport.h"
 
@@ -4904,6 +4907,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
 		 */
 		if (unlikely(ata_tag_internal(qc->tag))) {
 			fill_result_tf(qc);
+			trace_ata_qc_complete_internal(qc);
 			__ata_qc_complete(qc);
 			return;
 		}
@@ -4914,6 +4918,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
 		 */
 		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
 			fill_result_tf(qc);
+			trace_ata_qc_complete_failed(qc);
 			ata_qc_schedule_eh(qc);
 			return;
 		}
@@ -4924,6 +4929,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
 		if (qc->flags & ATA_QCFLAG_RESULT_TF)
 			fill_result_tf(qc);
 
+		trace_ata_qc_complete_done(qc);
 		/* Some commands need post-processing after successful
 		 * completion.
 		 */
@@ -5071,7 +5077,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
 	}
 
 	ap->ops->qc_prep(qc);
-
+	trace_ata_qc_issue(qc);
 	qc->err_mask |= ap->ops->qc_issue(qc);
 	if (unlikely(qc->err_mask))
 		goto err;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 77ef43e..07f41be 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -46,6 +46,7 @@
 
 #include <linux/libata.h>
 
+#include <trace/events/libata.h>
 #include "libata.h"
 
 enum {
@@ -2291,6 +2292,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
 		all_err_mask |= qc->err_mask;
 		if (qc->flags & ATA_QCFLAG_IO)
 			eflags |= ATA_EFLAG_IS_IO;
+		trace_ata_eh_link_autopsy_qc(qc);
 	}
 
 	/* enforce default EH actions */
@@ -2325,7 +2327,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
 			eflags |= ATA_EFLAG_DUBIOUS_XFER;
 		ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask);
 	}
-
+	trace_ata_eh_link_autopsy(dev, ehc->i.action, all_err_mask);
 	DPRINTK("EXIT\n");
 }
 
diff --git a/drivers/ata/libata-trace.c b/drivers/ata/libata-trace.c
new file mode 100644
index 0000000..fd30b8c
--- /dev/null
+++ b/drivers/ata/libata-trace.c
@@ -0,0 +1,151 @@
+/*
+ * libata-trace.c - trace functions for libata
+ *
+ * Copyright 2015 Hannes Reinecke
+ * Copyright 2015 SUSE Linux GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/trace_seq.h>
+#include <trace/events/libata.h>
+
+const char *
+libata_trace_parse_status(struct trace_seq *p, unsigned char status)
+{
+	const char *ret = trace_seq_buffer_ptr(p);
+
+	trace_seq_printf(p, "{ ");
+	if (status & ATA_BUSY)
+		trace_seq_printf(p, "BUSY ");
+	if (status & ATA_DRDY)
+		trace_seq_printf(p, "DRDY ");
+	if (status & ATA_DF)
+		trace_seq_printf(p, "DF ");
+	if (status & ATA_DSC)
+		trace_seq_printf(p, "DSC ");
+	if (status & ATA_DRQ)
+		trace_seq_printf(p, "DRQ ");
+	if (status & ATA_CORR)
+		trace_seq_printf(p, "CORR ");
+	if (status & ATA_SENSE)
+		trace_seq_printf(p, "SENSE ");
+	if (status & ATA_ERR)
+		trace_seq_printf(p, "ERR ");
+	trace_seq_putc(p, '}');
+	trace_seq_putc(p, 0);
+
+	return ret;
+}
+
+const char *
+libata_trace_parse_eh_action(struct trace_seq *p, unsigned int eh_action)
+{
+	const char *ret = trace_seq_buffer_ptr(p);
+
+	trace_seq_printf(p, "%x", eh_action);
+	if (eh_action) {
+		trace_seq_printf(p, "{ ");
+		if (eh_action & ATA_EH_REVALIDATE)
+			trace_seq_printf(p, "REVALIDATE ");
+		if (eh_action & (ATA_EH_SOFTRESET | ATA_EH_HARDRESET))
+			trace_seq_printf(p, "RESET ");
+		else if (eh_action & ATA_EH_SOFTRESET)
+			trace_seq_printf(p, "SOFTRESET ");
+		else if (eh_action & ATA_EH_HARDRESET)
+			trace_seq_printf(p, "HARDRESET ");
+		if (eh_action & ATA_EH_ENABLE_LINK)
+			trace_seq_printf(p, "ENABLE_LINK ");
+		if (eh_action & ATA_EH_PARK)
+			trace_seq_printf(p, "PARK ");
+		trace_seq_putc(p, '}');
+	}
+	trace_seq_putc(p, 0);
+
+	return ret;
+}
+
+const char *
+libata_trace_parse_eh_err_mask(struct trace_seq *p, unsigned int eh_err_mask)
+{
+	const char *ret = trace_seq_buffer_ptr(p);
+
+	trace_seq_printf(p, "%x", eh_err_mask);
+	if (eh_err_mask) {
+		trace_seq_printf(p, "{ ");
+		if (eh_err_mask & AC_ERR_DEV)
+			trace_seq_printf(p, "DEV ");
+		if (eh_err_mask & AC_ERR_HSM)
+			trace_seq_printf(p, "HSM ");
+		if (eh_err_mask & AC_ERR_TIMEOUT)
+			trace_seq_printf(p, "TIMEOUT ");
+		if (eh_err_mask & AC_ERR_MEDIA)
+			trace_seq_printf(p, "MEDIA ");
+		if (eh_err_mask & AC_ERR_ATA_BUS)
+			trace_seq_printf(p, "ATA_BUS ");
+		if (eh_err_mask & AC_ERR_HOST_BUS)
+			trace_seq_printf(p, "HOST_BUS ");
+		if (eh_err_mask & AC_ERR_SYSTEM)
+			trace_seq_printf(p, "SYSTEM ");
+		if (eh_err_mask & AC_ERR_INVALID)
+			trace_seq_printf(p, "INVALID ");
+		if (eh_err_mask & AC_ERR_OTHER)
+			trace_seq_printf(p, "OTHER ");
+		if (eh_err_mask & AC_ERR_NODEV_HINT)
+			trace_seq_printf(p, "NODEV_HINT ");
+		if (eh_err_mask & AC_ERR_NCQ)
+			trace_seq_printf(p, "NCQ ");
+		trace_seq_putc(p, '}');
+	}
+	trace_seq_putc(p, 0);
+
+	return ret;
+}
+
+const char *
+libata_trace_parse_qc_flags(struct trace_seq *p, unsigned int qc_flags)
+{
+	const char *ret = trace_seq_buffer_ptr(p);
+
+	trace_seq_printf(p, "%x", qc_flags);
+	if (qc_flags) {
+		trace_seq_printf(p, "{ ");
+		if (qc_flags & ATA_QCFLAG_ACTIVE)
+			trace_seq_printf(p, "ACTIVE ");
+		if (qc_flags & ATA_QCFLAG_DMAMAP)
+			trace_seq_printf(p, "DMAMAP ");
+		if (qc_flags & ATA_QCFLAG_IO)
+			trace_seq_printf(p, "IO ");
+		if (qc_flags & ATA_QCFLAG_RESULT_TF)
+			trace_seq_printf(p, "RESULT_TF ");
+		if (qc_flags & ATA_QCFLAG_CLEAR_EXCL)
+			trace_seq_printf(p, "CLEAR_EXCL ");
+		if (qc_flags & ATA_QCFLAG_QUIET)
+			trace_seq_printf(p, "QUIET ");
+		if (qc_flags & ATA_QCFLAG_RETRY)
+			trace_seq_printf(p, "RETRY ");
+		if (qc_flags & ATA_QCFLAG_FAILED)
+			trace_seq_printf(p, "FAILED ");
+		if (qc_flags & ATA_QCFLAG_SENSE_VALID)
+			trace_seq_printf(p, "SENSE_VALID ");
+		if (qc_flags & ATA_QCFLAG_EH_SCHEDULED)
+			trace_seq_printf(p, "EH_SCHEDULED ");
+		trace_seq_putc(p, '}');
+	}
+	trace_seq_putc(p, 0);
+
+	return ret;
+}
diff --git a/include/trace/events/libata.h b/include/trace/events/libata.h
new file mode 100644
index 0000000..8b0fbd9
--- /dev/null
+++ b/include/trace/events/libata.h
@@ -0,0 +1,325 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM libata
+
+#if !defined(_TRACE_LIBATA_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_LIBATA_H
+
+#include <linux/ata.h>
+#include <linux/libata.h>
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#define ata_opcode_name(opcode)	{ opcode, #opcode }
+#define show_opcode_name(val)					\
+	__print_symbolic(val,					\
+		 ata_opcode_name(ATA_CMD_DEV_RESET),		\
+		 ata_opcode_name(ATA_CMD_CHK_POWER),		\
+		 ata_opcode_name(ATA_CMD_STANDBY),		\
+		 ata_opcode_name(ATA_CMD_IDLE),			\
+		 ata_opcode_name(ATA_CMD_EDD),			\
+		 ata_opcode_name(ATA_CMD_DOWNLOAD_MICRO),	\
+		 ata_opcode_name(ATA_CMD_DOWNLOAD_MICRO_DMA),	\
+		 ata_opcode_name(ATA_CMD_NOP),			\
+		 ata_opcode_name(ATA_CMD_FLUSH),		\
+		 ata_opcode_name(ATA_CMD_FLUSH_EXT),		\
+		 ata_opcode_name(ATA_CMD_ID_ATA),		\
+		 ata_opcode_name(ATA_CMD_ID_ATAPI),		\
+		 ata_opcode_name(ATA_CMD_SERVICE),		\
+		 ata_opcode_name(ATA_CMD_READ),			\
+		 ata_opcode_name(ATA_CMD_READ_EXT),		\
+		 ata_opcode_name(ATA_CMD_READ_QUEUED),		\
+		 ata_opcode_name(ATA_CMD_READ_STREAM_EXT),	\
+		 ata_opcode_name(ATA_CMD_READ_STREAM_DMA_EXT),	\
+		 ata_opcode_name(ATA_CMD_WRITE),		\
+		 ata_opcode_name(ATA_CMD_WRITE_EXT),		\
+		 ata_opcode_name(ATA_CMD_WRITE_QUEUED),		\
+		 ata_opcode_name(ATA_CMD_WRITE_STREAM_EXT),	\
+		 ata_opcode_name(ATA_CMD_WRITE_STREAM_DMA_EXT), \
+		 ata_opcode_name(ATA_CMD_WRITE_FUA_EXT),	\
+		 ata_opcode_name(ATA_CMD_WRITE_QUEUED_FUA_EXT), \
+		 ata_opcode_name(ATA_CMD_FPDMA_READ),		\
+		 ata_opcode_name(ATA_CMD_FPDMA_WRITE),		\
+		 ata_opcode_name(ATA_CMD_FPDMA_SEND),		\
+		 ata_opcode_name(ATA_CMD_FPDMA_RECV),		\
+		 ata_opcode_name(ATA_CMD_PIO_READ),		\
+		 ata_opcode_name(ATA_CMD_PIO_READ_EXT),		\
+		 ata_opcode_name(ATA_CMD_PIO_WRITE),		\
+		 ata_opcode_name(ATA_CMD_PIO_WRITE_EXT),	\
+		 ata_opcode_name(ATA_CMD_READ_MULTI),		\
+		 ata_opcode_name(ATA_CMD_READ_MULTI_EXT),	\
+		 ata_opcode_name(ATA_CMD_WRITE_MULTI),		\
+		 ata_opcode_name(ATA_CMD_WRITE_MULTI_EXT),	\
+		 ata_opcode_name(ATA_CMD_WRITE_MULTI_FUA_EXT),	\
+		 ata_opcode_name(ATA_CMD_SET_FEATURES),		\
+		 ata_opcode_name(ATA_CMD_SET_MULTI),		\
+		 ata_opcode_name(ATA_CMD_PACKET),		\
+		 ata_opcode_name(ATA_CMD_VERIFY),		\
+		 ata_opcode_name(ATA_CMD_VERIFY_EXT),		\
+		 ata_opcode_name(ATA_CMD_WRITE_UNCORR_EXT),	\
+		 ata_opcode_name(ATA_CMD_STANDBYNOW1),		\
+		 ata_opcode_name(ATA_CMD_IDLEIMMEDIATE),	\
+		 ata_opcode_name(ATA_CMD_SLEEP),		\
+		 ata_opcode_name(ATA_CMD_INIT_DEV_PARAMS),	\
+		 ata_opcode_name(ATA_CMD_READ_NATIVE_MAX),	\
+		 ata_opcode_name(ATA_CMD_READ_NATIVE_MAX_EXT),	\
+		 ata_opcode_name(ATA_CMD_SET_MAX),		\
+		 ata_opcode_name(ATA_CMD_SET_MAX_EXT),		\
+		 ata_opcode_name(ATA_CMD_READ_LOG_EXT),		\
+		 ata_opcode_name(ATA_CMD_WRITE_LOG_EXT),	\
+		 ata_opcode_name(ATA_CMD_READ_LOG_DMA_EXT),	\
+		 ata_opcode_name(ATA_CMD_WRITE_LOG_DMA_EXT),	\
+		 ata_opcode_name(ATA_CMD_TRUSTED_NONDATA),	\
+		 ata_opcode_name(ATA_CMD_TRUSTED_RCV),		\
+		 ata_opcode_name(ATA_CMD_TRUSTED_RCV_DMA),	\
+		 ata_opcode_name(ATA_CMD_TRUSTED_SND),		\
+		 ata_opcode_name(ATA_CMD_TRUSTED_SND_DMA),	\
+		 ata_opcode_name(ATA_CMD_PMP_READ),		\
+		 ata_opcode_name(ATA_CMD_PMP_READ_DMA),		\
+		 ata_opcode_name(ATA_CMD_PMP_WRITE),		\
+		 ata_opcode_name(ATA_CMD_PMP_WRITE_DMA),	\
+		 ata_opcode_name(ATA_CMD_CONF_OVERLAY),		\
+		 ata_opcode_name(ATA_CMD_SEC_SET_PASS),		\
+		 ata_opcode_name(ATA_CMD_SEC_UNLOCK),		\
+		 ata_opcode_name(ATA_CMD_SEC_ERASE_PREP),	\
+		 ata_opcode_name(ATA_CMD_SEC_ERASE_UNIT),	\
+		 ata_opcode_name(ATA_CMD_SEC_FREEZE_LOCK),	\
+		 ata_opcode_name(ATA_CMD_SEC_DISABLE_PASS),	\
+		 ata_opcode_name(ATA_CMD_CONFIG_STREAM),	\
+		 ata_opcode_name(ATA_CMD_SMART),		\
+		 ata_opcode_name(ATA_CMD_MEDIA_LOCK),		\
+		 ata_opcode_name(ATA_CMD_MEDIA_UNLOCK),		\
+		 ata_opcode_name(ATA_CMD_DSM),			\
+		 ata_opcode_name(ATA_CMD_CHK_MED_CRD_TYP),	\
+		 ata_opcode_name(ATA_CMD_CFA_REQ_EXT_ERR),	\
+		 ata_opcode_name(ATA_CMD_CFA_WRITE_NE),		\
+		 ata_opcode_name(ATA_CMD_CFA_TRANS_SECT),	\
+		 ata_opcode_name(ATA_CMD_CFA_ERASE),		\
+		 ata_opcode_name(ATA_CMD_CFA_WRITE_MULT_NE),	\
+		 ata_opcode_name(ATA_CMD_REQ_SENSE_DATA),	\
+		 ata_opcode_name(ATA_CMD_SANITIZE_DEVICE),	\
+		 ata_opcode_name(ATA_CMD_RESTORE),		\
+		 ata_opcode_name(ATA_CMD_READ_LONG),		\
+		 ata_opcode_name(ATA_CMD_READ_LONG_ONCE),	\
+		 ata_opcode_name(ATA_CMD_WRITE_LONG),		\
+		 ata_opcode_name(ATA_CMD_WRITE_LONG_ONCE))
+
+#define ata_error_name(result)	{ result, #result }
+#define show_error_name(val)				\
+	__print_symbolic(val,				\
+		ata_error_name(ATA_ICRC),		\
+		ata_error_name(ATA_UNC),		\
+		ata_error_name(ATA_MC),			\
+		ata_error_name(ATA_IDNF),		\
+		ata_error_name(ATA_MCR),		\
+		ata_error_name(ATA_ABORTED),		\
+		ata_error_name(ATA_TRK0NF),		\
+		ata_error_name(ATA_AMNF))
+
+#define ata_protocol_name(proto)	{ proto, #proto }
+#define show_protocol_name(val)				\
+	__print_symbolic(val,				\
+		ata_protocol_name(ATA_PROT_UNKNOWN),	\
+		ata_protocol_name(ATA_PROT_NODATA),	\
+		ata_protocol_name(ATA_PROT_PIO),	\
+		ata_protocol_name(ATA_PROT_DMA),	\
+		ata_protocol_name(ATA_PROT_NCQ),	\
+		ata_protocol_name(ATAPI_PROT_NODATA),	\
+		ata_protocol_name(ATAPI_PROT_PIO),	\
+		ata_protocol_name(ATAPI_PROT_DMA))
+
+const char *libata_trace_parse_status(struct trace_seq*, unsigned char);
+#define __parse_status(s) libata_trace_parse_status(p, s)
+
+const char *libata_trace_parse_eh_action(struct trace_seq *, unsigned int);
+#define __parse_eh_action(a) libata_trace_parse_eh_action(p, a)
+
+const char *libata_trace_parse_eh_err_mask(struct trace_seq *, unsigned int);
+#define __parse_eh_err_mask(m) libata_trace_parse_eh_err_mask(p, m)
+
+const char *libata_trace_parse_qc_flags(struct trace_seq *, unsigned int);
+#define __parse_qc_flags(f) libata_trace_parse_qc_flags(p, f)
+
+TRACE_EVENT(ata_qc_issue,
+
+	TP_PROTO(struct ata_queued_cmd *qc),
+
+	TP_ARGS(qc),
+
+	TP_STRUCT__entry(
+		__field( unsigned int,	ata_port )
+		__field( unsigned int,	ata_dev	)
+		__field( unsigned int,	tag	)
+		__field( unsigned char,	cmd	)
+		__field( unsigned char,	dev	)
+		__field( unsigned char,	lbal	)
+		__field( unsigned char,	lbam	)
+		__field( unsigned char,	lbah	)
+		__field( unsigned char,	nsect	)
+		__field( unsigned char,	feature	)
+		__field( unsigned char,	hob_lbal )
+		__field( unsigned char,	hob_lbam )
+		__field( unsigned char,	hob_lbah )
+		__field( unsigned char,	hob_nsect )
+		__field( unsigned char,	hob_feature )
+		__field( unsigned char,	ctl )
+		__field( unsigned char,	proto )
+		__field( unsigned long,	flags )
+	),
+
+	TP_fast_assign(
+		__entry->ata_port	= qc->ap->print_id;
+		__entry->ata_dev	= qc->dev->link->pmp + qc->dev->devno;
+		__entry->tag		= qc->tag;
+		__entry->proto		= qc->tf.protocol;
+		__entry->cmd		= qc->tf.command;
+		__entry->dev		= qc->tf.device;
+		__entry->lbal		= qc->tf.lbal;
+		__entry->lbam		= qc->tf.lbam;
+		__entry->lbah		= qc->tf.lbah;
+		__entry->hob_lbal	= qc->tf.hob_lbal;
+		__entry->hob_lbam	= qc->tf.hob_lbam;
+		__entry->hob_lbah	= qc->tf.hob_lbah;
+		__entry->feature	= qc->tf.feature;
+		__entry->hob_feature	= qc->tf.hob_feature;
+		__entry->nsect		= qc->tf.nsect;
+		__entry->hob_nsect	= qc->tf.hob_nsect;
+	),
+
+	TP_printk("ata_port=%u ata_dev=%u tag=%d proto=%s cmd=%s " \
+		  " tf=(%02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x)",
+		  __entry->ata_port, __entry->ata_dev, __entry->tag,
+		  show_protocol_name(__entry->proto),
+		  show_opcode_name(__entry->cmd),
+		  __entry->cmd, __entry->feature, __entry->nsect,
+		  __entry->lbal, __entry->lbam, __entry->lbah,
+		  __entry->hob_feature, __entry->hob_nsect,
+		  __entry->hob_lbal, __entry->hob_lbam, __entry->hob_lbah,
+		  __entry->dev)
+);
+
+DECLARE_EVENT_CLASS(ata_qc_complete_template,
+
+	TP_PROTO(struct ata_queued_cmd *qc),
+
+	TP_ARGS(qc),
+
+	TP_STRUCT__entry(
+		__field( unsigned int,	ata_port )
+		__field( unsigned int,	ata_dev	)
+		__field( unsigned int,	tag	)
+		__field( unsigned char,	status	)
+		__field( unsigned char,	dev	)
+		__field( unsigned char,	lbal	)
+		__field( unsigned char,	lbam	)
+		__field( unsigned char,	lbah	)
+		__field( unsigned char,	nsect	)
+		__field( unsigned char,	error	)
+		__field( unsigned char,	hob_lbal )
+		__field( unsigned char,	hob_lbam )
+		__field( unsigned char,	hob_lbah )
+		__field( unsigned char,	hob_nsect )
+		__field( unsigned char,	hob_feature )
+		__field( unsigned char,	ctl )
+		__field( unsigned long,	flags )
+	),
+
+	TP_fast_assign(
+		__entry->ata_port	= qc->ap->print_id;
+		__entry->ata_dev	= qc->dev->link->pmp + qc->dev->devno;
+		__entry->tag		= qc->tag;
+		__entry->status		= qc->result_tf.command;
+		__entry->dev		= qc->result_tf.device;
+		__entry->lbal		= qc->result_tf.lbal;
+		__entry->lbam		= qc->result_tf.lbam;
+		__entry->lbah		= qc->result_tf.lbah;
+		__entry->hob_lbal	= qc->result_tf.hob_lbal;
+		__entry->hob_lbam	= qc->result_tf.hob_lbam;
+		__entry->hob_lbah	= qc->result_tf.hob_lbah;
+		__entry->error		= qc->result_tf.feature;
+		__entry->hob_feature	= qc->result_tf.hob_feature;
+		__entry->nsect		= qc->result_tf.nsect;
+		__entry->hob_nsect	= qc->result_tf.hob_nsect;
+	),
+
+	TP_printk("ata_port=%u ata_dev=%u tag=%d flags=%s status=%s " \
+		  " res=(%02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x)",
+		  __entry->ata_port, __entry->ata_dev, __entry->tag,
+		  __parse_qc_flags(__entry->flags),
+		  __parse_status(__entry->status),
+		  __entry->status, __entry->error, __entry->nsect,
+		  __entry->lbal, __entry->lbam, __entry->lbah,
+		  __entry->hob_feature, __entry->hob_nsect,
+		  __entry->hob_lbal, __entry->hob_lbam, __entry->hob_lbah,
+		  __entry->dev)
+);
+
+DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_internal,
+	     TP_PROTO(struct ata_queued_cmd *qc),
+	     TP_ARGS(qc));
+
+DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_failed,
+	     TP_PROTO(struct ata_queued_cmd *qc),
+	     TP_ARGS(qc));
+
+DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_done,
+	     TP_PROTO(struct ata_queued_cmd *qc),
+	     TP_ARGS(qc));
+
+TRACE_EVENT(ata_eh_link_autopsy,
+
+	TP_PROTO(struct ata_device *dev, unsigned int eh_action, unsigned int eh_err_mask),
+
+	TP_ARGS(dev, eh_action, eh_err_mask),
+
+	TP_STRUCT__entry(
+		__field( unsigned int,	ata_port )
+		__field( unsigned int,	ata_dev	)
+		__field( unsigned int,	eh_action )
+		__field( unsigned int,	eh_err_mask)
+	),
+
+	TP_fast_assign(
+		__entry->ata_port	= dev->link->ap->print_id;
+		__entry->ata_dev	= dev->link->pmp + dev->devno;
+		__entry->eh_action	= eh_action;
+		__entry->eh_err_mask	= eh_err_mask;
+	),
+
+	TP_printk("ata_port=%u ata_dev=%u eh_action=%s err_mask=%s",
+		  __entry->ata_port, __entry->ata_dev,
+		  __parse_eh_action(__entry->eh_action),
+		  __parse_eh_err_mask(__entry->eh_err_mask))
+);
+
+TRACE_EVENT(ata_eh_link_autopsy_qc,
+
+	TP_PROTO(struct ata_queued_cmd *qc),
+
+	TP_ARGS(qc),
+
+	TP_STRUCT__entry(
+		__field( unsigned int,	ata_port )
+		__field( unsigned int,	ata_dev	)
+		__field( unsigned int,	tag	)
+		__field( unsigned int,	qc_flags )
+		__field( unsigned int,	eh_err_mask)
+	),
+
+	TP_fast_assign(
+		__entry->ata_port	= qc->ap->print_id;
+		__entry->ata_dev	= qc->dev->link->pmp + qc->dev->devno;
+		__entry->tag		= qc->tag;
+		__entry->qc_flags	= qc->flags;
+		__entry->eh_err_mask	= qc->err_mask;
+	),
+
+	TP_printk("ata_port=%u ata_dev=%u tag=%d flags=%s err_mask=%s",
+		  __entry->ata_port, __entry->ata_dev, __entry->tag,
+		  __parse_qc_flags(__entry->qc_flags),
+		  __parse_eh_err_mask(__entry->eh_err_mask))
+);
+
+#endif /*  _TRACE_LIBATA_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
-- 
1.8.5.2

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

* Re: [PATCH 0/9] libata sense code update
  2015-03-27 15:46 [PATCH 0/9] libata sense code update Hannes Reinecke
                   ` (8 preceding siblings ...)
  2015-03-27 15:46 ` [PATCH 9/9] libata: Add tracepoints Hannes Reinecke
@ 2015-03-27 16:01 ` Tejun Heo
  9 siblings, 0 replies; 12+ messages in thread
From: Tejun Heo @ 2015-03-27 16:01 UTC (permalink / raw)
  To: Hannes Reinecke; +Cc: linux-ide, linux-kernel

On Fri, Mar 27, 2015 at 04:46:29PM +0100, Hannes Reinecke wrote:
> 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.

Applied 1-9 to libata/for-4.1.

Thanks a lot for the excellent patchset.

-- 
tejun

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

* Re: [PATCH 4/9] ide,ata: Rename ATA_IDX to ATA_SENSE
  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
  0 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2015-03-31 17:07 UTC (permalink / raw)
  To: hare; +Cc: tj, linux-ide, linux-kernel

From: Hannes Reinecke <hare@suse.de>
Date: Fri, 27 Mar 2015 16:46:33 +0100

> ATA-8 defines bit 1 as 'ATA_SENSE', not 'ATA_IDX'.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>

Acked-by: David S. Miller <davem@davemloft.net>

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

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

Thread overview: 12+ 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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).