diff options
author | Mark Lord <liml@rtr.ca> | 2009-03-11 00:56:00 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-03-24 22:35:41 -0400 |
commit | 6abf4678261218938ccdac90767d34ce9937634f (patch) | |
tree | 673a08435f33d75fc1aa7ec32b60308392535aba /drivers/ata/sata_mv.c | |
parent | 2b748a0a344847fe6b924407bbe153e1878c9f09 (diff) | |
download | lwn-6abf4678261218938ccdac90767d34ce9937634f.tar.gz lwn-6abf4678261218938ccdac90767d34ce9937634f.zip |
sata_mv: optimize IRQ coalescing for 8-port chips
Enable use of the "all ports" IRQ coalescing optimization
for GEN_II / GEN_IIE chips that have dual host-controllers (8-ports).
Currently only the 6081 chip qualifies, but other chips may come along someday.
Rather than each half of the chip having to satisfy a local set of coalescing thresholds,
use of this feature groups all ports together under a single set of thresholds.
Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r-- | drivers/ata/sata_mv.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index ef385451ffd5..47184567248d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1016,7 +1016,7 @@ static void mv_set_irq_coalescing(struct ata_host *host, void __iomem *mmio = hpriv->base, *hc_mmio; u32 coal_enable = 0; unsigned long flags; - unsigned int clks; + unsigned int clks, is_dual_hc = hpriv->n_ports > MV_PORTS_PER_HC; const u32 coal_disable = PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | ALL_PORTS_COAL_DONE; @@ -1033,37 +1033,41 @@ static void mv_set_irq_coalescing(struct ata_host *host, } spin_lock_irqsave(&host->lock, flags); + mv_set_main_irq_mask(host, coal_disable, 0); -#if 0 /* disabled pending functional clarification from Marvell */ - if (!IS_GEN_I(hpriv)) { + if (is_dual_hc && !IS_GEN_I(hpriv)) { /* - * GEN_II/GEN_IIE: global thresholds for the entire chip. + * GEN_II/GEN_IIE with dual host controllers: + * one set of global thresholds for the entire chip. */ writel(clks, mmio + MV_IRQ_COAL_TIME_THRESHOLD); writel(count, mmio + MV_IRQ_COAL_IO_THRESHOLD); /* clear leftover coal IRQ bit */ - writelfl(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); - clks = count = 0; /* so as to clear the alternate regs below */ - coal_enable = ALL_PORTS_COAL_DONE; + writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); + if (count) + coal_enable = ALL_PORTS_COAL_DONE; + clks = count = 0; /* force clearing of regular regs below */ } -#endif + /* * All chips: independent thresholds for each HC on the chip. */ hc_mmio = mv_hc_base_from_port(mmio, 0); writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); - coal_enable |= PORTS_0_3_COAL_DONE; - if (hpriv->n_ports > 4) { + writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS); + if (count) + coal_enable |= PORTS_0_3_COAL_DONE; + if (is_dual_hc) { hc_mmio = mv_hc_base_from_port(mmio, MV_PORTS_PER_HC); writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); - coal_enable |= PORTS_4_7_COAL_DONE; + writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS); + if (count) + coal_enable |= PORTS_4_7_COAL_DONE; } - if (!count) - coal_enable = 0; - mv_set_main_irq_mask(host, coal_disable, coal_enable); + mv_set_main_irq_mask(host, 0, coal_enable); spin_unlock_irqrestore(&host->lock, flags); } |