linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 4/5] libata: implement ata_tf_read_block()
  2006-11-14 13:37 [PATCHSET] libata: improve sense data generation Tejun Heo
                   ` (3 preceding siblings ...)
  2006-11-14 13:37 ` [PATCH 3/5] libata: cosmetic changes to sense generation functions Tejun Heo
@ 2006-11-14 13:37 ` Tejun Heo
  4 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-14 13:37 UTC (permalink / raw)
  To: jgarzik, linux-ide; +Cc: Tejun Heo

Implement ata_tf_read_block().

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/libata-core.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 drivers/ata/libata.h      |    1 +
 2 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 476df94..dab577c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -240,6 +240,49 @@ int ata_rwcmd_protocol(struct ata_queued
 }
 
 /**
+ *	ata_tf_read_block - Read block address from ATA taskfile
+ *	@tf: ATA taskfile of interest
+ *	@dev: ATA device @tf belongs to
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	Read block address from @tf.  This function can handle all
+ *	three address formats - LBA, LBA48 and CHS.  tf->protocol and
+ *	flags select the address format to use.
+ *
+ *	RETURNS:
+ *	Block address read from @tf.
+ */
+u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
+{
+	u64 block = 0;
+
+	if (tf->flags & ATA_TFLAG_LBA) {
+		if (tf->flags & ATA_TFLAG_LBA48) {
+			block |= (u64)tf->hob_lbah << 40;
+			block |= (u64)tf->hob_lbam << 32;
+			block |= tf->hob_lbal << 24;
+		} else
+			block |= (tf->device & 0xf) << 24;
+
+		block |= tf->lbah << 16;
+		block |= tf->lbam << 8;
+		block |= tf->lbal;
+	} else {
+		u32 cyl, head, sect;
+
+		cyl = tf->lbam | (tf->lbah << 8);
+		head = tf->device & 0xf;
+		sect = tf->lbal;
+
+		block = (cyl * dev->heads + head) * dev->sectors + sect;
+	}
+
+	return block;
+}
+
+/**
  *	ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask
  *	@pio_mask: pio_mask
  *	@mwdma_mask: mwdma_mask
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index e4ffb2e..0549b19 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -45,6 +45,7 @@ extern int atapi_dmadir;
 extern int libata_fua;
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
 extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
 extern void ata_dev_disable(struct ata_device *dev);
 extern void ata_port_flush_task(struct ata_port *ap);
 extern unsigned ata_exec_internal(struct ata_device *dev,
-- 
1.4.3.3



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

* [PATCH 3/5] libata: cosmetic changes to sense generation functions
  2006-11-14 13:37 [PATCHSET] libata: improve sense data generation Tejun Heo
                   ` (2 preceding siblings ...)
  2006-11-14 13:37 ` [PATCH 2/5] libata: fix passthru sense data header Tejun Heo
@ 2006-11-14 13:37 ` Tejun Heo
  2006-11-14 13:37 ` [PATCH 4/5] libata: implement ata_tf_read_block() Tejun Heo
  4 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-14 13:37 UTC (permalink / raw)
  To: jgarzik, linux-ide; +Cc: Tejun Heo

* s/ata_gen_ata_desc_sense/ata_gen_passthru_sense/

* s/ata_gen_fixed_sense/ata_gen_ata_sense/

* make both functions static

* neither function has locking requirement, change it to None.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/libata-scsi.c |   22 +++++++++++-----------
 1 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 8c9fa9e..2004a76 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -671,7 +671,7 @@ void ata_to_sense_error(unsigned id, u8
 }
 
 /*
- *	ata_gen_ata_desc_sense - Generate check condition sense block.
+ *	ata_gen_passthru_sense - Generate check condition sense block.
  *	@qc: Command that completed.
  *
  *	This function is specific to the ATA descriptor format sense
@@ -681,9 +681,9 @@ void ata_to_sense_error(unsigned id, u8
  *	block. Clear sense key, ASC & ASCQ if there is no error.
  *
  *	LOCKING:
- *	spin_lock_irqsave(host lock)
+ *	None.
  */
-void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
+static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct ata_taskfile *tf = &qc->result_tf;
@@ -743,16 +743,16 @@ void ata_gen_ata_desc_sense(struct ata_q
 }
 
 /**
- *	ata_gen_fixed_sense - generate a SCSI fixed sense block
+ *	ata_gen_ata_sense - generate a SCSI fixed sense block
  *	@qc: Command that we are erroring out
  *
  *	Leverage ata_to_sense_error() to give us the codes.  Fit our
  *	LBA in here if there's room.
  *
  *	LOCKING:
- *	inherited from caller
+ *	None.
  */
-void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
+static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct ata_taskfile *tf = &qc->result_tf;
@@ -1459,7 +1459,7 @@ static void ata_scsi_qc_complete(struct
 	 */
 	if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
  	    ((cdb[2] & 0x20) || need_sense)) {
- 		ata_gen_ata_desc_sense(qc);
+		ata_gen_passthru_sense(qc);
 	} else {
 		if (!need_sense) {
 			cmd->result = SAM_STAT_GOOD;
@@ -1470,7 +1470,7 @@ static void ata_scsi_qc_complete(struct
 			 * good for smaller LBA (and maybe CHS?)
 			 * devices.
 			 */
-			ata_gen_fixed_sense(qc);
+			ata_gen_ata_sense(qc);
 		}
 	}
 
@@ -2301,7 +2301,7 @@ static void atapi_sense_complete(struct
 		 * a sense descriptors, since that's only
 		 * correct for ATA, not ATAPI
 		 */
-		ata_gen_ata_desc_sense(qc);
+		ata_gen_passthru_sense(qc);
 	}
 
 	qc->scsidone(qc->scsicmd);
@@ -2376,7 +2376,7 @@ static void atapi_qc_complete(struct ata
 			 * sense descriptors, since that's only
 			 * correct for ATA, not ATAPI
 			 */
-			ata_gen_ata_desc_sense(qc);
+			ata_gen_passthru_sense(qc);
 		}
 
 		/* SCSI EH automatically locks door if sdev->locked is
@@ -2409,7 +2409,7 @@ static void atapi_qc_complete(struct ata
 		 * a sense descriptors, since that's only
 		 * correct for ATA, not ATAPI
 		 */
-		ata_gen_ata_desc_sense(qc);
+		ata_gen_passthru_sense(qc);
 	} else {
 		u8 *scsicmd = cmd->cmnd;
 
-- 
1.4.3.3



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

* [PATCH 5/5] libata: improve SCSI sense data generation
  2006-11-14 13:37 [PATCHSET] libata: improve sense data generation Tejun Heo
@ 2006-11-14 13:37 ` Tejun Heo
  2006-11-14 13:37 ` [PATCH 1/5] libata: sync result_tf.flags w/ command tf.flags Tejun Heo
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-14 13:37 UTC (permalink / raw)
  To: jgarzik, linux-ide; +Cc: Tejun Heo

Update ata_gen_ata_sense() to use desc format sense data to report the
first failed block.  The first failed block is read from result_tf
using ata_tf_read_block() which can handle all three address formats.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/libata-scsi.c |   46 ++++++++++++++++++++++----------------------
 1 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 2004a76..9b0d59d 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -746,53 +746,53 @@ static void ata_gen_passthru_sense(struc
  *	ata_gen_ata_sense - generate a SCSI fixed sense block
  *	@qc: Command that we are erroring out
  *
- *	Leverage ata_to_sense_error() to give us the codes.  Fit our
- *	LBA in here if there's room.
+ *	Generate sense block for a failed ATA command @qc.  Descriptor
+ *	format is used to accomodate LBA48 block address.
  *
  *	LOCKING:
  *	None.
  */
 static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
 {
+	struct ata_device *dev = qc->dev;
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct ata_taskfile *tf = &qc->result_tf;
 	unsigned char *sb = cmd->sense_buffer;
+	unsigned char *desc = sb + 8;
 	int verbose = qc->ap->ops->error_handler == NULL;
+	u64 block;
 
 	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
 	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
-	/*
-	 * Use ata_to_sense_error() to map status register bits
+	/* sense data is current and format is descriptor */
+	sb[0] = 0x72;
+
+	/* Use ata_to_sense_error() to map status register bits
 	 * onto sense key, asc & ascq.
 	 */
 	if (qc->err_mask ||
 	    tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
 		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
-				   &sb[2], &sb[12], &sb[13], verbose);
-		sb[2] &= 0x0f;
+				   &sb[1], &sb[2], &sb[3], verbose);
+		sb[1] &= 0x0f;
 	}
 
-	sb[0] = 0x70;
-	sb[7] = 0x0a;
+	block = ata_tf_read_block(&qc->result_tf, dev);
 
-	if (tf->flags & ATA_TFLAG_LBA48) {
-		/* TODO: find solution for LBA48 descriptors */
-	}
+	/* information sense data descriptor */
+	sb[7] = 12;
+	desc[0] = 0x00;
+	desc[1] = 10;
 
-	else if (tf->flags & ATA_TFLAG_LBA) {
-		/* A small (28b) LBA will fit in the 32b info field */
-		sb[0] |= 0x80;		/* set valid bit */
-		sb[3] = tf->device & 0x0f;
-		sb[4] = tf->lbah;
-		sb[5] = tf->lbam;
-		sb[6] = tf->lbal;
-	}
-
-	else {
-		/* TODO: C/H/S */
-	}
+	desc[2] |= 0x80;	/* valid */
+	desc[6] = block >> 40;
+	desc[7] = block >> 32;
+	desc[8] = block >> 24;
+	desc[9] = block >> 16;
+	desc[10] = block >> 8;
+	desc[11] = block;
 }
 
 static void ata_scsi_sdev_config(struct scsi_device *sdev)
-- 
1.4.3.3



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

* [PATCHSET] libata: improve sense data generation
@ 2006-11-14 13:37 Tejun Heo
  2006-11-14 13:37 ` [PATCH 5/5] libata: improve SCSI " Tejun Heo
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-14 13:37 UTC (permalink / raw)
  To: jgarzik, linux-ide, htejun

Hello, Jeff.

This patchset fixes and improves SCSI sense data generation.

* resul_tf->flags is synced to command tf->flags so that sense
  generation functions can tell which address format is in use

* length field in passthru sense data fixed

* failed block is now properly reported for all three address formats
  - CHS, LBA and LBA48.

* other cleanups

Thanks.

--
tejun


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

* [PATCH 2/5] libata: fix passthru sense data header
  2006-11-14 13:37 [PATCHSET] libata: improve sense data generation Tejun Heo
  2006-11-14 13:37 ` [PATCH 5/5] libata: improve SCSI " Tejun Heo
  2006-11-14 13:37 ` [PATCH 1/5] libata: sync result_tf.flags w/ command tf.flags Tejun Heo
@ 2006-11-14 13:37 ` Tejun Heo
  2006-11-14 13:37 ` [PATCH 3/5] libata: cosmetic changes to sense generation functions Tejun Heo
  2006-11-14 13:37 ` [PATCH 4/5] libata: implement ata_tf_read_block() Tejun Heo
  4 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-14 13:37 UTC (permalink / raw)
  To: jgarzik, linux-ide; +Cc: Tejun Heo

sb[7] should contain the length of whole information sense data
descriptor while desc[1] should contain the number of following bytes
in the descriptor.  ie. 14 for sb[7] but 12 for desc[1].

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/libata-scsi.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a0b6ee1..8c9fa9e 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -713,12 +713,9 @@ void ata_gen_ata_desc_sense(struct ata_q
 
 	desc[0] = 0x09;
 
-	/*
-	 * Set length of additional sense data.
-	 * Since we only populate descriptor 0, the total
-	 * length is the same (fixed) length as descriptor 0.
-	 */
-	desc[1] = sb[7] = 14;
+	/* set length of additional sense data */
+	sb[7] = 14;
+	desc[1] = 12;
 
 	/*
 	 * Copy registers into sense buffer.
-- 
1.4.3.3



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

* [PATCH 1/5] libata: sync result_tf.flags w/ command tf.flags
  2006-11-14 13:37 [PATCHSET] libata: improve sense data generation Tejun Heo
  2006-11-14 13:37 ` [PATCH 5/5] libata: improve SCSI " Tejun Heo
@ 2006-11-14 13:37 ` Tejun Heo
  2006-11-14 19:33   ` Jeff Garzik
  2006-11-14 13:37 ` [PATCH 2/5] libata: fix passthru sense data header Tejun Heo
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: Tejun Heo @ 2006-11-14 13:37 UTC (permalink / raw)
  To: jgarzik, linux-ide; +Cc: Tejun Heo

libata didn't initialize result_tf.flags which indicates transfer type
(RW/FUA) and address type (CHS/LBA/LBA48).  ata_gen_fixed_sense()
assumed result_tf.flags equals command tf.flags and failed to report
the first failed block to SCSI layer because zero tf flags indicates
CHS and bad block reporting for CHS is not implemented.

Implement fill_result_tf() which sets result_tf.flags to command
tf.flags and use it to fill result_tf.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/libata-core.c |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 994bc27..476df94 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4516,6 +4516,14 @@ void __ata_qc_complete(struct ata_queued
 	qc->complete_fn(qc);
 }
 
+static void fill_result_tf(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	ap->ops->tf_read(ap, &qc->result_tf);
+	qc->result_tf.flags = qc->tf.flags;
+}
+
 /**
  *	ata_qc_complete - Complete an active ATA command
  *	@qc: Command to complete
@@ -4553,7 +4561,7 @@ void ata_qc_complete(struct ata_queued_c
 		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
 			if (!ata_tag_internal(qc->tag)) {
 				/* always fill result TF for failed qc */
-				ap->ops->tf_read(ap, &qc->result_tf);
+				fill_result_tf(qc);
 				ata_qc_schedule_eh(qc);
 				return;
 			}
@@ -4561,7 +4569,7 @@ void ata_qc_complete(struct ata_queued_c
 
 		/* read result TF if requested */
 		if (qc->flags & ATA_QCFLAG_RESULT_TF)
-			ap->ops->tf_read(ap, &qc->result_tf);
+			fill_result_tf(qc);
 
 		__ata_qc_complete(qc);
 	} else {
@@ -4570,7 +4578,7 @@ void ata_qc_complete(struct ata_queued_c
 
 		/* read result TF if failed or requested */
 		if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
-			ap->ops->tf_read(ap, &qc->result_tf);
+			fill_result_tf(qc);
 
 		__ata_qc_complete(qc);
 	}
-- 
1.4.3.3



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

* Re: [PATCH 1/5] libata: sync result_tf.flags w/ command tf.flags
  2006-11-14 13:37 ` [PATCH 1/5] libata: sync result_tf.flags w/ command tf.flags Tejun Heo
@ 2006-11-14 19:33   ` Jeff Garzik
  0 siblings, 0 replies; 7+ messages in thread
From: Jeff Garzik @ 2006-11-14 19:33 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linux-ide

Tejun Heo wrote:
> libata didn't initialize result_tf.flags which indicates transfer type
> (RW/FUA) and address type (CHS/LBA/LBA48).  ata_gen_fixed_sense()
> assumed result_tf.flags equals command tf.flags and failed to report
> the first failed block to SCSI layer because zero tf flags indicates
> CHS and bad block reporting for CHS is not implemented.
> 
> Implement fill_result_tf() which sets result_tf.flags to command
> tf.flags and use it to fill result_tf.
> 
> Signed-off-by: Tejun Heo <htejun@gmail.com>

applied patches 1-5

consider combining patch #4 and patch #5, when a similar situation 
arises in the future



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

end of thread, other threads:[~2006-11-14 19:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-14 13:37 [PATCHSET] libata: improve sense data generation Tejun Heo
2006-11-14 13:37 ` [PATCH 5/5] libata: improve SCSI " Tejun Heo
2006-11-14 13:37 ` [PATCH 1/5] libata: sync result_tf.flags w/ command tf.flags Tejun Heo
2006-11-14 19:33   ` Jeff Garzik
2006-11-14 13:37 ` [PATCH 2/5] libata: fix passthru sense data header Tejun Heo
2006-11-14 13:37 ` [PATCH 3/5] libata: cosmetic changes to sense generation functions Tejun Heo
2006-11-14 13:37 ` [PATCH 4/5] libata: implement ata_tf_read_block() 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).