From: Mark Lord <liml@rtr.ca>
To: Tejun Heo <htejun@gmail.com>
Cc: Jeff Garzik <jeff@garzik.org>,
Alan Cox <alan@lxorguk.ukuu.org.uk>, Alan Cox <alan@redhat.com>,
IDE/ATA development list <linux-ide@vger.kernel.org>
Subject: Re: libata fails to recover from HSM violation involving DRQ status
Date: Sun, 29 Apr 2007 08:59:01 -0400 [thread overview]
Message-ID: <46349695.7080706@rtr.ca> (raw)
In-Reply-To: <463487F0.4040701@rtr.ca>
Mark Lord wrote:
> Tejun Heo wrote:
>> Tejun Heo wrote:
>> ..
>>> Anyways, can you try to hack it into ata_bmdma_error_handler() and see
>>> whether it actually works? You can check for AC_ERR_HSM there and drain
>>> data port if DRQ is set. After HSM, ATA_NIEN is set and the port should
>>> be quiescent at that point.
>
> Sure, I'll do that here shortly.
Okay, it recovers nicely now with the patch below,
which I'm including for illustrative purposes only.
Ideally, we would look into the qc to see how large
the request was, and determine the drain "limit" based
on that. But I got tired of rebooting and just hardcoded
it for the time being.
For my failed IDENTIFY, it claims 255 iterations.
Which makes sense, as tf_read probably already read one word
of the 256 words in the pipeline.
Draining is a nice workaround for most problems,
but we cannot drain for a WRITE --> wrong data direction,
and I don't want to feed bad data *into* the output FIFO.
Mmm.. I guess I'll have to try a failed WRITE under the
same circumstances and see what that does. Probably it just
recovers without any fuss, as the FIFO will be empty anyway.
>> Ah.. one more thing, is this draining also needed after DMA commands or
>> only after PIO commands?
My drive doesn't do IDENTIFY_DMA, so I fed it a READ_DMA instead
with "no data", and libata recovered without draining.
Here's the hack I used:
--- linux/drivers/ata/libata-sff.c.orig 2007-04-26 12:02:46.000000000 -0400
+++ linux/drivers/ata/libata-sff.c 2007-04-29 08:29:27.000000000 -0400
@@ -413,6 +413,24 @@
ap->ops->irq_on(ap);
}
+static void ata_drain_fifo (struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+ u8 stat = ata_chk_status(ap);
+ /*
+ * Try to clear stuck DRQ if necessary.
+ */
+ if ((stat & ATA_DRQ) && (!qc || qc->dma_dir != DMA_TO_DEVICE)) {
+ unsigned int i, limit = 512;
+ printk("Draining up to %u words from data FIFO.\n", limit);
+ for (i = 0; i < limit ; ++i) {
+ ioread16(ap->ioaddr.data_addr);
+ if (!(ata_chk_status(ap) & ATA_DRQ))
+ break;
+ }
+ printk("Drained %u/%u words.\n", i, limit);
+ }
+}
+
/**
* ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
* @ap: port to handle error for
@@ -469,7 +487,7 @@
}
ata_altstatus(ap);
- ata_chk_status(ap);
+ ata_drain_fifo(ap, qc);
ap->ops->irq_clear(ap);
spin_unlock_irqrestore(ap->lock, flags);
next prev parent reply other threads:[~2007-04-29 12:59 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-28 20:15 libata fails to recover from HSM violation involving DRQ status Mark Lord
2007-04-28 20:18 ` Mark Lord
2007-04-28 20:30 ` Alan Cox
2007-04-28 20:37 ` Jeff Garzik
2007-04-28 20:44 ` Mark Lord
2007-04-28 20:50 ` Jeff Garzik
2007-04-28 21:25 ` Alan Cox
2007-04-28 21:35 ` Mark Lord
2007-04-28 21:38 ` Jeff Garzik
2007-04-28 21:41 ` Mark Lord
2007-04-29 3:17 ` Tejun Heo
2007-04-29 3:46 ` Jeff Garzik
2007-04-29 7:45 ` Tejun Heo
2007-04-29 3:51 ` Tejun Heo
2007-04-29 11:56 ` Mark Lord
2007-04-29 12:59 ` Mark Lord [this message]
2007-04-29 13:13 ` Mark Lord
2007-04-29 16:42 ` Tejun Heo
2007-04-29 16:47 ` Mark Lord
2007-04-29 18:49 ` Mark Lord
2007-04-29 19:05 ` Mark Lord
2007-04-30 0:59 ` Tejun Heo
2007-04-29 19:07 ` Mark Lord
2007-04-30 0:54 ` Tejun Heo
2007-04-30 3:42 ` Mark Lord
2007-04-30 3:58 ` Tejun Heo
2007-04-30 17:47 ` Mark Lord
2007-05-01 0:23 ` Mark Lord
2007-05-01 2:47 ` Tejun Heo
2007-05-01 13:00 ` Mark Lord
2007-05-11 3:33 ` Mark Lord
2007-05-11 3:35 ` Mark Lord
2007-04-29 12:07 ` Mark Lord
2007-04-29 16:36 ` Tejun Heo
2007-04-28 23:56 ` Alan Cox
2007-04-28 22:09 ` Mark Lord
2007-04-29 3:04 ` Tejun Heo
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=46349695.7080706@rtr.ca \
--to=liml@rtr.ca \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=alan@redhat.com \
--cc=htejun@gmail.com \
--cc=jeff@garzik.org \
--cc=linux-ide@vger.kernel.org \
/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 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).