From: Mark Lord <liml@rtr.ca>
To: Jeff Garzik <jgarzik@pobox.com>, Tejun Heo <htejun@gmail.com>,
IDE/ATA development list <linux-ide@vger.kernel.org>
Subject: [PATCH 08/12] sata_mv fix mv_host_intr bug for hc_irq_cause
Date: Fri, 02 May 2008 02:13:27 -0400 [thread overview]
Message-ID: <481AB107.701@rtr.ca> (raw)
In-Reply-To: <481AB0D2.3070103@rtr.ca>
Remove the unwanted reads of hc_irq_cause from mv_host_intr(),
thereby removing a bug whereby we were not always reading it when needed..
Signed-off-by: Mark Lord <mlord@pobox.com>
--- old/drivers/ata/sata_mv.c 2008-05-01 20:01:29.000000000 -0400
+++ linux/drivers/ata/sata_mv.c 2008-05-01 20:15:59.000000000 -0400
@@ -1818,48 +1818,61 @@
static int mv_host_intr(struct ata_host *host, u32 main_irq_cause)
{
struct mv_host_priv *hpriv = host->private_data;
- void __iomem *mmio = hpriv->base, *hc_mmio = NULL;
- u32 hc_irq_cause = 0;
+ void __iomem *mmio = hpriv->base, *hc_mmio;
unsigned int handled = 0, port;
for (port = 0; port < hpriv->n_ports; port++) {
struct ata_port *ap = host->ports[port];
struct mv_port_priv *pp;
- unsigned int shift, hardport, port_cause;
- /*
- * When we move to the second hc, flag our cached
- * copies of hc_mmio (and hc_irq_cause) as invalid again.
- */
- if (port == MV_PORTS_PER_HC)
- hc_mmio = NULL;
- /*
- * Do nothing if port is not interrupting or is disabled:
- */
+ unsigned int p, shift, hardport, port_cause;
+
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
- port_cause = (main_irq_cause >> shift) & (DONE_IRQ | ERR_IRQ);
- if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED))
- continue;
/*
- * Each hc within the host has its own hc_irq_cause register.
- * We defer reading it until we know we need it, right now:
- *
- * FIXME later: we don't really need to read this register
- * (some logic changes required below if we go that way),
- * because it doesn't tell us anything new. But we do need
- * to write to it, outside the top of this loop,
- * to reset the interrupt triggers for next time.
+ * Each hc within the host has its own hc_irq_cause register,
+ * where the interrupting ports bits get ack'd.
*/
- if (!hc_mmio) {
+ if (hardport == 0) { /* first port on this hc ? */
+ u32 hc_cause = (main_irq_cause >> shift) & HC0_IRQ_PEND;
+ u32 port_mask, ack_irqs;
+ /*
+ * Skip this entire hc if nothing pending for any ports
+ */
+ if (!hc_cause) {
+ port += MV_PORTS_PER_HC - 1;
+ continue;
+ }
+ /*
+ * We don't need/want to read the hc_irq_cause register,
+ * because doing so hurts performance, and
+ * main_irq_cause already gives us everything we need.
+ *
+ * But we do have to *write* to the hc_irq_cause to ack
+ * the ports that we are handling this time through.
+ *
+ * This requires that we create a bitmap for those
+ * ports which interrupted us, and use that bitmap
+ * to ack (only) those ports via hc_irq_cause.
+ */
+ ack_irqs = 0;
+ for (p = 0; p < MV_PORTS_PER_HC; ++p) {
+ if ((port + p) >= hpriv->n_ports)
+ break;
+ port_mask = (DONE_IRQ | ERR_IRQ) << (p * 2);
+ if (hc_cause & port_mask)
+ ack_irqs |= (DMA_IRQ | DEV_IRQ) << p;
+ }
hc_mmio = mv_hc_base_from_port(mmio, port);
- hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
- writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+ writelfl(~ack_irqs, hc_mmio + HC_IRQ_CAUSE_OFS);
handled = 1;
}
+ port_cause = (main_irq_cause >> shift) & (DONE_IRQ | ERR_IRQ);
+ if (!port_cause)
+ continue;
/*
* Process completed CRPB response(s) before other events.
*/
pp = ap->private_data;
- if (hc_irq_cause & (DMA_IRQ << hardport)) {
+ if (port_cause & DONE_IRQ) {
if (pp->pp_flags & MV_PP_FLAG_EDMA_EN)
mv_process_crpb_entries(ap, pp);
}
@@ -1868,15 +1881,15 @@
*/
if (unlikely(port_cause & ERR_IRQ)) {
mv_err_intr(ap);
- } else if (hc_irq_cause & (DEV_IRQ << hardport)) {
+ } else {
if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
struct ata_queued_cmd *qc = mv_get_active_qc(ap);
if (qc) {
ata_sff_host_intr(ap, qc);
continue;
}
+ mv_unexpected_intr(ap);
}
- mv_unexpected_intr(ap);
}
}
return handled;
next prev parent reply other threads:[~2008-05-02 6:13 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-02 6:07 [PATCH 00/12] sata_mv: The last big set for 2.6.26 Mark Lord
2008-05-02 6:07 ` [PATCH 01/12] sata_mv more cosmetic changes Mark Lord
2008-05-02 6:08 ` [PATCH 02/12] sata_mv pci features Mark Lord
2008-05-02 6:09 ` [PATCH 03/12] sata_mv wait for empty+idle Mark Lord
2008-05-02 6:10 ` [PATCH 04/12] sata_mv new mv_qc_defer method Mark Lord
2008-05-02 6:10 ` [PATCH 05/12] sata_mv errata workaround for sata25 part 1 Mark Lord
2008-05-02 6:11 ` [PATCH 06/12] sata_mv rearrange mv_config_fbs Mark Lord
2008-05-02 6:12 ` [PATCH 07/12] sata_mv NCQ and SError fixes for mv_err_intr Mark Lord
2008-05-02 6:13 ` Mark Lord [this message]
2008-05-02 6:14 ` [PATCH 09/12] sata_mv new mv_port_intr function Mark Lord
2008-05-02 6:14 ` [PATCH 10/12] sata_mv libata: export ata_eh_analyze_ncq_error Mark Lord
2008-05-02 6:15 ` [PATCH 11/12] sata_mv delayed eh handling Mark Lord
2008-05-02 6:16 ` [PATCH 12/12] sata_mv NCQ-EH for FIS-based switching Mark Lord
2008-05-02 12:44 ` Mark Lord
2008-05-02 16:52 ` Grant Grundler
2008-05-02 16:54 ` Grant Grundler
2008-05-02 17:46 ` Mark Lord
2008-05-02 17:52 ` Alan Cox
2008-05-02 17:56 ` [PATCH 13/13] sata_mv use hweight16() for bit counting Mark Lord
2008-05-02 18:02 ` Mark Lord
2008-05-02 18:02 ` [PATCH 13/13] sata_mv use hweight16() for bit counting (V2) Mark Lord
2008-05-02 18:31 ` Grant Grundler
2008-05-02 16:42 ` [PATCH 03/12] sata_mv wait for empty+idle Grant Grundler
2008-05-02 17:45 ` Mark Lord
2008-05-02 18:39 ` Grant Grundler
2008-05-02 20:09 ` Mark Lord
2008-05-02 16:06 ` [PATCH 02/12] sata_mv pci features Grant Grundler
2008-05-02 17:41 ` Mark Lord
2008-05-02 18:28 ` Grant Grundler
2008-05-06 14:10 ` [PATCH 01/12] sata_mv more cosmetic changes Jeff Garzik
2008-05-06 17:57 ` Mark Lord
2008-05-06 14:17 ` 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=481AB107.701@rtr.ca \
--to=liml@rtr.ca \
--cc=htejun@gmail.com \
--cc=jgarzik@pobox.com \
--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).