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 13/16] libata-eh-fw: activate ->error_handler
Date: Tue, 11 Apr 2006 22:42:55 +0900	[thread overview]
Message-ID: <11447629753003-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <11447629733305-git-send-email-htejun@gmail.com>

Update ata_scsi_error() such that ->error_handler is invoked if
implemented.  ata_scsi_error() also takes care of merging
ATA_QCFLAG_TIMEOUT into qc->err_mask and clearing SCSI EH conditions.

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

---

 drivers/scsi/libata-eh.c |   56 +++++++++++++++++++++++++++++++++++++++++++---
 include/linux/libata.h   |    3 ++
 2 files changed, 55 insertions(+), 4 deletions(-)

dc24434e3e0ed074dd1f11231e9f0fc50e457d13
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 97ec527..1015f89 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -123,18 +123,66 @@ enum scsi_eh_timer_return ata_scsi_timed
 int ata_scsi_error(struct Scsi_Host *host)
 {
 	struct ata_port *ap = (struct ata_port *)&host->hostdata[0];
+	spinlock_t *hs_lock = &ap->host_set->lock;
+	int repeat_cnt = ATA_EH_MAX_REPEAT;
+	unsigned long flags;
 
 	DPRINTK("ENTER\n");
 
+ repeat:
 	/* synchronize with IRQ handler and port task */
-	spin_unlock_wait(&ap->host_set->lock);
+	spin_unlock_wait(hs_lock);
 	ata_port_flush_task(ap);
 
-	WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
+	/* invoke error handler */
+	if (ap->ops->error_handler) {
+		int i;
+
+		/* for new EH, all the qc's are ours now */
+		for (i = 0; i < ATA_MAX_QUEUE; i++) {
+			struct ata_queued_cmd *qc;
+			qc = __ata_qc_from_tag(ap, i);
+			if (qc->flags & ATA_QCFLAG_TIMEOUT)
+				qc->err_mask |= AC_ERR_TIMEOUT;;
+		}
+
+		/* invoke EH */
+		ap->ops->error_handler(ap);
 
-	ap->ops->eng_timeout(ap);
+		/* Exception might have happend after ->error_handler
+		 * recovered the port but before reaching this point.
+		 * repeat EH if that happens.
+		 */
+		spin_lock_irqsave(hs_lock, flags);
+
+		if (ap->flags & ATA_FLAG_FROZEN) {
+			if (--repeat_cnt) {
+				printk(KERN_INFO "ata%u: port is frozen after "
+				       "EH completed, repeating EH (cnt=%d)\n",
+				       ap->id, repeat_cnt);
+				spin_unlock_irqrestore(hs_lock, flags);
+				goto repeat;
+			}
+			printk(KERN_ERR "ata%u: port is frozen after %d tries, "
+			       "giving up\n", ap->id, ATA_EH_MAX_REPEAT);
+		}
+
+		/* Clear host_eh_scheduled while holding hs_lock such
+		 * that if exception occurs after this point but
+		 * before EH completion, SCSI midlayer will
+		 * re-initiate EH.
+		 */
+		host->host_eh_scheduled = 0;
+
+		spin_unlock_irqrestore(hs_lock, flags);
+	} else {
+		WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
+		ap->ops->eng_timeout(ap);
+	}
 
-	WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
+	/* finish or retry handled scmd's and clean up */
+	WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q) ||
+		host->host_eh_scheduled);
 
 	scsi_eh_flush_done_q(&ap->eh_done_q);
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 47fbd68..0ac5214 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -226,6 +226,9 @@ enum {
 	ATA_EH_ABORT		= (1 << 0), /* abort all active commands */
 	ATA_EH_FREEZE		= (1 << 1), /* freeze port (implies ABORT) */
 
+	/* max repeat if error condition is still set after ->error_handler */
+	ATA_EH_MAX_REPEAT	= 5,
+
 	/* how hard are we gonna try to probe/recover devices */
 	ATA_PROBE_MAX_TRIES	= 3,
 };
-- 
1.2.4



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

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-04-11 13:42 [PATCHSET 5/9] new EH framework, take 2 Tejun Heo
2006-04-11 13:42 ` [PATCH 01/16] libata-eh-fw: add flags for new EH Tejun Heo
2006-04-11 13:42 ` [PATCH 02/16] libata-eh-fw: add new EH operations Tejun Heo
2006-04-11 13:42 ` [PATCH 07/16] libata-eh-fw: implement ata_port_freeze() Tejun Heo
2006-04-11 13:42 ` [PATCH 05/16] libata-eh-fw: clear SError in ata_std_postreset() Tejun Heo
2006-04-11 13:42 ` [PATCH 12/16] libata-eh-fw: implement new EH scheduling from PIO Tejun Heo
2006-04-11 13:42 ` [PATCH 10/16] libata-eh-fw: implement ata_eh_schedule_port() Tejun Heo
2006-04-11 13:42 ` [PATCH 06/16] libata-eh-fw: use special reserved tag and qc for internal commands Tejun Heo
2006-04-11 13:42 ` [PATCH 11/16] libata-eh-fw: implement new EH scheduling via timeout Tejun Heo
2006-04-12 22:36   ` Jeff Garzik
2006-04-13  2:40     ` Tejun Heo
2006-04-13  3:18       ` Jeff Garzik
2006-04-13  3:36         ` Tejun Heo
2006-04-27 11:33           ` Jeff Garzik
2006-04-29 21:13             ` Alan Cox
2006-04-11 13:42 ` [PATCH 08/16] libata-eh-fw: update ata_qc_from_tag() to enforce normal/EH qc ownership Tejun Heo
2006-04-11 13:42 ` [PATCH 04/16] libata-eh-fw: clear IRQ in ata_std_postreset() Tejun Heo
2006-04-11 13:42 ` [PATCH 09/16] libata-eh-fw: implement new EH scheduling via error completion Tejun Heo
2006-04-11 13:42 ` [PATCH 03/16] libata-eh-fw: hold host_set lock while finishing internal qc Tejun Heo
2006-04-11 13:42 ` [PATCH 16/16] libata-eh-fw: update ata_interrupt() to handle frozen port properly Tejun Heo
2006-04-12 22:40   ` Jeff Garzik
2006-04-13  2:59     ` Tejun Heo
2006-04-11 13:42 ` [PATCH 15/16] libata-eh-fw: update SCSI command completion path for new EH Tejun Heo
2006-04-11 13:42 ` Tejun Heo [this message]
2006-04-11 13:42 ` [PATCH 14/16] libata-eh-fw: activate ->post_internal_cmd Tejun Heo
2006-04-12 22:41 ` [PATCHSET 5/9] new EH framework, 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=11447629753003-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.