All of lore.kernel.org
 help / color / mirror / Atom feed
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;

  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 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.