Commit c4de573b authored by Mark Lord's avatar Mark Lord Committed by Jeff Garzik

sata_mv: consolidate main_irq_mask updates

Part two of simplifying/fixing handling of the main_irq_mask register
to resolve unexpected interrupt issues observed in 2.6.26-rc*.

Consolidate all updates of the host main_irq_mask register
into a single function.  This simplifies maintenance,
and also prepares the way for caching it (later).

No functionality changes in this update.
Signed-off-by: default avatarMark Lord <mlord@pobox.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 51de32d2
...@@ -837,6 +837,31 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio, ...@@ -837,6 +837,31 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
} }
static void mv_set_main_irq_mask(struct ata_host *host,
u32 disable_bits, u32 enable_bits)
{
struct mv_host_priv *hpriv = host->private_data;
u32 old_mask, new_mask;
old_mask = readl(hpriv->main_irq_mask_addr);
new_mask = (old_mask & ~disable_bits) | enable_bits;
if (new_mask != old_mask)
writelfl(new_mask, hpriv->main_irq_mask_addr);
}
static void mv_enable_port_irqs(struct ata_port *ap,
unsigned int port_bits)
{
unsigned int shift, hardport, port = ap->port_no;
u32 disable_bits, enable_bits;
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
disable_bits = (DONE_IRQ | ERR_IRQ) << shift;
enable_bits = port_bits << shift;
mv_set_main_irq_mask(ap->host, disable_bits, enable_bits);
}
/** /**
* mv_start_dma - Enable eDMA engine * mv_start_dma - Enable eDMA engine
* @base: port base address * @base: port base address
...@@ -2383,7 +2408,6 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio) ...@@ -2383,7 +2408,6 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
ZERO(MV_PCI_DISC_TIMER); ZERO(MV_PCI_DISC_TIMER);
ZERO(MV_PCI_MSI_TRIGGER); ZERO(MV_PCI_MSI_TRIGGER);
writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT_OFS); writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT_OFS);
ZERO(PCI_HC_MAIN_IRQ_MASK_OFS);
ZERO(MV_PCI_SERR_MASK); ZERO(MV_PCI_SERR_MASK);
ZERO(hpriv->irq_cause_ofs); ZERO(hpriv->irq_cause_ofs);
ZERO(hpriv->irq_mask_ofs); ZERO(hpriv->irq_mask_ofs);
...@@ -2755,32 +2779,18 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, ...@@ -2755,32 +2779,18 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
static void mv_eh_freeze(struct ata_port *ap) static void mv_eh_freeze(struct ata_port *ap)
{ {
struct mv_host_priv *hpriv = ap->host->private_data;
unsigned int shift, hardport, port = ap->port_no;
u32 main_irq_mask;
/* FIXME: handle coalescing completion events properly */
mv_stop_edma(ap); mv_stop_edma(ap);
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport); mv_enable_port_irqs(ap, 0);
/* disable assertion of portN err, done events */
main_irq_mask = readl(hpriv->main_irq_mask_addr);
main_irq_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
} }
static void mv_eh_thaw(struct ata_port *ap) static void mv_eh_thaw(struct ata_port *ap)
{ {
struct mv_host_priv *hpriv = ap->host->private_data; struct mv_host_priv *hpriv = ap->host->private_data;
unsigned int shift, hardport, port = ap->port_no; unsigned int port = ap->port_no;
unsigned int hardport = mv_hardport_from_port(port);
void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port); void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
void __iomem *port_mmio = mv_ap_base(ap); void __iomem *port_mmio = mv_ap_base(ap);
u32 main_irq_mask, hc_irq_cause; u32 hc_irq_cause;
/* FIXME: handle coalescing completion events properly */
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
/* clear EDMA errors on this port */ /* clear EDMA errors on this port */
writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
...@@ -2790,10 +2800,7 @@ static void mv_eh_thaw(struct ata_port *ap) ...@@ -2790,10 +2800,7 @@ static void mv_eh_thaw(struct ata_port *ap)
hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport); hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport);
writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
/* enable assertion of portN err, done events */ mv_enable_port_irqs(ap, DONE_IRQ | ERR_IRQ);
main_irq_mask = readl(hpriv->main_irq_mask_addr);
main_irq_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
} }
/** /**
...@@ -3046,7 +3053,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) ...@@ -3046,7 +3053,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
} }
/* global interrupt mask: 0 == mask everything */ /* global interrupt mask: 0 == mask everything */
writel(0, hpriv->main_irq_mask_addr); mv_set_main_irq_mask(host, ~0, 0);
n_hc = mv_get_hc_count(host->ports[0]->flags); n_hc = mv_get_hc_count(host->ports[0]->flags);
...@@ -3099,7 +3106,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) ...@@ -3099,7 +3106,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
* enable only global host interrupts for now. * enable only global host interrupts for now.
* The per-port interrupts get done later as ports are set up. * The per-port interrupts get done later as ports are set up.
*/ */
writelfl(PCI_ERR, hpriv->main_irq_mask_addr); mv_set_main_irq_mask(host, 0, PCI_ERR);
} }
done: done:
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment