summary refs log tree commit diff
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2008-05-17 13:38:00 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-05-19 17:30:11 -0400
commit96e2c487933e5f69e98fffdcae2c35c78a671c07 (patch)
tree418ff66ed6e6aaaef8775e1b6d03d6c799fc6b4c
parenta44253d24a97ec3efe601267274a5fb64d8696c1 (diff)
downloadlinux-96e2c487933e5f69e98fffdcae2c35c78a671c07.tar.gz
sata_mv: cache main_irq_mask register in hpriv
Part five of simplifying/fixing handling of the main_irq_mask register
to resolve unexpected interrupt issues observed in 2.6.26-rc*.

Keep a cached copy of the main_irq_mask so that we don't have
to stall the CPU to read it on every pass through mv_interrupt.

This significantly speeds up interrupt handling, both for sata_mv,
and for any other driver/device sharing the same PCI IRQ line.

Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/sata_mv.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index eb7f3dafb502..2d8a7e894b7b 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -458,6 +458,7 @@ struct mv_port_signal {
 
 struct mv_host_priv {
 	u32			hp_flags;
+	u32			main_irq_mask;
 	struct mv_port_signal	signal[8];
 	const struct mv_hw_ops	*ops;
 	int			n_ports;
@@ -843,10 +844,12 @@ static void mv_set_main_irq_mask(struct ata_host *host,
 	struct mv_host_priv *hpriv = host->private_data;
 	u32 old_mask, new_mask;
 
-	old_mask = readl(hpriv->main_irq_mask_addr);
+	old_mask = hpriv->main_irq_mask;
 	new_mask = (old_mask & ~disable_bits) | enable_bits;
-	if (new_mask != old_mask)
+	if (new_mask != old_mask) {
+		hpriv->main_irq_mask = new_mask;
 		writelfl(new_mask, hpriv->main_irq_mask_addr);
+	}
 }
 
 static void mv_enable_port_irqs(struct ata_port *ap,
@@ -2200,12 +2203,11 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
 	struct ata_host *host = dev_instance;
 	struct mv_host_priv *hpriv = host->private_data;
 	unsigned int handled = 0;
-	u32 main_irq_cause, main_irq_mask, pending_irqs;
+	u32 main_irq_cause, pending_irqs;
 
 	spin_lock(&host->lock);
 	main_irq_cause = readl(hpriv->main_irq_cause_addr);
-	main_irq_mask  = readl(hpriv->main_irq_mask_addr);
-	pending_irqs   = main_irq_cause & main_irq_mask;
+	pending_irqs   = main_irq_cause & hpriv->main_irq_mask;
 	/*
 	 * Deal with cases where we either have nothing pending, or have read
 	 * a bogus register value which can indicate HW removal or PCI fault.