All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tejun Heo <htejun@gmail.com>
To: jgarzik@pobox.com, alan@lxorguk.ukuu.org.uk, axboe@suse.de,
	albertcc@tw.ibm.com, lkosewsk@gmail.com,
	linux-ide@vger.kernel.org
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 08/15] libata-ncq: update EH to handle NCQ
Date: Tue, 11 Apr 2006 22:53:37 +0900	[thread overview]
Message-ID: <11447636171050-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <1144763616819-git-send-email-htejun@gmail.com>

* ata_eh_determine_qc() is updated to take log page 10h into account
  to determine which qc has failed and obtain its TF.

* ata_eh_report() is updated to report ap->sactive.

* ata_eh_finish_qcs() is updated to finish all aborted NCQ commands.

Signed-off-by: Tejun Heo <htejun@gmail.com>

---

 drivers/scsi/ahci.c         |    2 +
 drivers/scsi/libata-bmdma.c |    2 +
 drivers/scsi/libata-eh.c    |   79 +++++++++++++++++++++++++++++++++++++++++--
 drivers/scsi/sata_sil24.c   |    2 +
 include/linux/libata.h      |    1 +
 5 files changed, 80 insertions(+), 6 deletions(-)

80d986bf527942c9a6188b258b15e2f5667678ff
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 67950ee..f3d117e 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -845,7 +845,7 @@ static void ahci_error_handler(struct at
 	/* perform recovery */
 	action |= ahci_eh_autopsy(ap, irq_stat, &err_mask, desc, sizeof(desc));
 
-	qc = ata_eh_determine_qc(ap, &tf);
+	qc = ata_eh_determine_qc(ap, 0, &tf);
 	if (qc)
 		qc->err_mask |= err_mask;
 
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index 6e48ce5..3c3bc71 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -700,7 +700,7 @@ void ata_bmdma_drive_eh(struct ata_port 
 	struct ata_taskfile tf;
 	u32 serror;
 
-	qc = ata_eh_determine_qc(ap, &tf);
+	qc = ata_eh_determine_qc(ap, 0, &tf);
 
 	/* reset PIO HSM and stop DMA engine */
 	spin_lock_irqsave(&host_set->lock, flags);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 795f580..1a87bce 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -669,6 +669,7 @@ static int ata_eh_read_log_10h(struct at
 /**
  *	ata_eh_determine_qc - Determine which qc caused error
  *	@ap: port which failed
+ *	@use_log_10h: use log page 10h result
  *	@tf: resulting taskfile registers of the failed command
  *
  *	Determine which qc caused failure and read associated tf
@@ -681,12 +682,65 @@ static int ata_eh_read_log_10h(struct at
  *	Pointer to the failed qc.
  */
 struct ata_queued_cmd * ata_eh_determine_qc(struct ata_port *ap,
+					    int use_log_10h,
 					    struct ata_taskfile *tf)
 {
+	struct ata_queued_cmd *first_qc, *qc;
+	struct ata_device *dev;
+	struct ata_taskfile tmp_tf;
+	unsigned int tag;
+	int rc;
+
 	memset(tf, 0, sizeof(*tf));
 	ap->ops->tf_read(ap, tf);
 
-	return __ata_qc_from_tag(ap, ap->active_tag);
+	qc = __ata_qc_from_tag(ap, ap->active_tag);
+	if (qc)
+		return qc;
+
+	if (!ap->sactive)
+		return NULL;
+
+	/* NCQ.  Assume the first device. */
+	dev = &ap->device[0];
+
+	/* Find the first active qc with error.  If no qc is
+	 * explicitly marked with error, use the first active qc.
+	 */
+	first_qc = NULL;
+	for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+		qc = __ata_qc_from_tag(ap, tag);
+		if (qc->flags & ATA_QCFLAG_ACTIVE) {
+			if (!first_qc)
+				first_qc = qc;
+			if (qc->err_mask)
+				break;
+		}
+	}
+	if (tag == ATA_MAX_QUEUE)
+		qc = first_qc;
+
+	/* Always read log page 10h to unjam the device but use the
+	 * result only if use_log_10h is non-zero.
+	 */
+	rc = ata_eh_read_log_10h(ap, dev, &tag, &tmp_tf);
+	if (rc || !(ap->sactive & (1 << tag))) {
+		if (rc == 0)
+			rc = -ENOENT;
+		printk(KERN_ERR "ata%u: failed to read log page 10h (errno=%d)\n",
+		       ap->id, rc);
+		qc->err_mask &= ~AC_ERR_DEV;
+		qc->err_mask |= AC_ERR_OTHER;
+	}
+	DPRINTK("ata%u: rc=%d emask=0x%x tag=%d stat=0x%x err=0x%x\n",
+		ap->id, rc, qc->err_mask, tag, tmp_tf.command, tmp_tf.feature);
+
+	if (use_log_10h) {
+		qc = __ata_qc_from_tag(ap, tag);
+		memcpy(tf, &tmp_tf, sizeof(*tf));
+	}
+
+	return qc;
 }
 
 /**
@@ -1018,11 +1072,11 @@ void ata_eh_report(struct ata_port *ap, 
 
 	printk(KERN_ERR
 	       "ata%u: dev %u command 0x%x tag %u failed with %s\n"
-	       "      Emask 0x%x stat 0x%x err 0x%x SErr 0x%x action 0x%x\n"
+	       "      Emask 0x%x stat 0x%x err 0x%x SAct 0x%x SErr 0x%x action 0x%x\n"
 	       "%s%s%s",
 	       ap->id, qc->dev->devno, qc->tf.command, qc->tag,
 	       ata_err_string(qc->err_mask), qc->err_mask,
-	       tf->command, tf->feature, serror, action,
+	       tf->command, tf->feature, ap->sactive, serror, action,
 	       desc_head, desc, desc_tail);
 }
 
@@ -1247,7 +1301,9 @@ void ata_eh_finish_qcs(struct ata_port *
 		       struct ata_taskfile *tf)
 {
 	struct ata_taskfile tmp_tf;
+	int i;
 
+	/* first, the failed qc */
 	if (qc) {
 		/* prevent infinite retry loop */
 		if (!qc->err_mask && !(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
@@ -1275,4 +1331,21 @@ void ata_eh_finish_qcs(struct ata_port *
 		else
 			ata_eh_qc_retry(qc);
 	}
+
+	/* and, victimized NCQ commands */
+
+	/* feed zero TF to sense generation */
+	memset(&tmp_tf, 0, sizeof(tmp_tf));
+
+	for (i = 0; i < ATA_MAX_QUEUE; i++) {
+		qc = __ata_qc_from_tag(ap, i);
+		if (qc->flags & ATA_QCFLAG_ACTIVE) {
+			tmp_tf.flags = qc->tf.flags;
+			tmp_tf.protocol = qc->tf.protocol;
+			tmp_tf.ctl = qc->tf.ctl;
+			qc->tf = tmp_tf;
+
+			ata_eh_qc_retry(qc);
+		}
+	}
 }
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index bbbc18a..c2c5ed9 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -821,7 +821,7 @@ static void sil24_error_handler(struct a
 	/* perform recovery */
 	action |= sil24_eh_autopsy(ap, irq_stat, &err_mask, desc, sizeof(desc));
 
-	qc = ata_eh_determine_qc(ap, &tf);
+	qc = ata_eh_determine_qc(ap, 0, &tf);
 	if (qc)
 		qc->err_mask |= err_mask;
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b194f3f..d463156 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -700,6 +700,7 @@ extern void ata_eh_schedule_port(struct 
 extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
 extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
 extern struct ata_queued_cmd * ata_eh_determine_qc(struct ata_port *ap,
+						   int use_log_10h,
 						   struct ata_taskfile *tf);
 extern unsigned int ata_eh_autopsy(struct ata_port *ap,
 				   struct ata_queued_cmd *qc,
-- 
1.2.4



  parent reply	other threads:[~2006-04-11 13:53 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-04-11 13:53 [PATCHSET 7/9] add NCQ support, take 2 Tejun Heo
2006-04-11 13:53 ` [PATCH 07/15] libata-ncq: implement ata_eh_read_log_10h() Tejun Heo
2006-04-11 13:53 ` [PATCH 03/15] libata-ncq: pass ata_scsi_translate() return value to SCSI midlayer Tejun Heo
2006-04-11 13:53 ` [PATCH 02/15] libata-ncq: add NCQ related libata flags Tejun Heo
2006-04-11 13:53 ` [PATCH 04/15] libata-ncq: implement ap->sactive Tejun Heo
2006-04-11 13:53 ` [PATCH 01/15] libata-ncq: add NCQ related ATA constants and id macros Tejun Heo
2006-04-11 13:53 ` [PATCH 06/15] libata-ncq: implement NCQ command translation Tejun Heo
2006-04-11 13:53 ` [PATCH 05/15] libata-ncq: implement command exclusion Tejun Heo
2006-04-11 13:53 ` [PATCH 12/15] ahci: add HOST_CAP_NCQ constant Tejun Heo
2006-04-11 13:53 ` [PATCH 13/15] ahci: kill pp->cmd_tbl_sg Tejun Heo
2006-04-11 13:53 ` [PATCH 09/15] libata-ncq: implement NCQ device configuration Tejun Heo
2006-04-11 13:53 ` [PATCH 15/15] sata_sil24: implement NCQ support Tejun Heo
2006-04-11 13:53 ` [PATCH 10/15] libata-ncq: implement ata_ncq_complete() Tejun Heo
2006-04-11 13:53 ` Tejun Heo [this message]
2006-04-11 13:53 ` [PATCH 14/15] ahci: implement NCQ suppport Tejun Heo
2006-04-11 13:53 ` [PATCH 11/15] ahci: clean up AHCI constants in preparation for NCQ Tejun Heo
2006-04-27  9:11 ` [PATCHSET 7/9] add NCQ support, take 2 Jeff Garzik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11447636171050-git-send-email-htejun@gmail.com \
    --to=htejun@gmail.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=albertcc@tw.ibm.com \
    --cc=axboe@suse.de \
    --cc=jgarzik@pobox.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=lkosewsk@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.