aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2008-05-17 13:35:21 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-05-19 17:29:10 -0400
commitc4de573b14d78ac83861d81d12977457d1e9cb6d (patch)
tree8831b6e4665649b8b3bd6a05dde1b032a0f0d6ce
parent51de32d200b21333950abc52ea1e589bc4eecef7 (diff)
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: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/sata_mv.c57
1 files changed, 32 insertions, 25 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 4e7948e29140..d0fd83635fa4 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -837,6 +837,31 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
837 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 837 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
838} 838}
839 839
840static void mv_set_main_irq_mask(struct ata_host *host,
841 u32 disable_bits, u32 enable_bits)
842{
843 struct mv_host_priv *hpriv = host->private_data;
844 u32 old_mask, new_mask;
845
846 old_mask = readl(hpriv->main_irq_mask_addr);
847 new_mask = (old_mask & ~disable_bits) | enable_bits;
848 if (new_mask != old_mask)
849 writelfl(new_mask, hpriv->main_irq_mask_addr);
850}
851
852static void mv_enable_port_irqs(struct ata_port *ap,
853 unsigned int port_bits)
854{
855 unsigned int shift, hardport, port = ap->port_no;
856 u32 disable_bits, enable_bits;
857
858 MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
859
860 disable_bits = (DONE_IRQ | ERR_IRQ) << shift;
861 enable_bits = port_bits << shift;
862 mv_set_main_irq_mask(ap->host, disable_bits, enable_bits);
863}
864
840/** 865/**
841 * mv_start_dma - Enable eDMA engine 866 * mv_start_dma - Enable eDMA engine
842 * @base: port base address 867 * @base: port base address
@@ -2383,7 +2408,6 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
2383 ZERO(MV_PCI_DISC_TIMER); 2408 ZERO(MV_PCI_DISC_TIMER);
2384 ZERO(MV_PCI_MSI_TRIGGER); 2409 ZERO(MV_PCI_MSI_TRIGGER);
2385 writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT_OFS); 2410 writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT_OFS);
2386 ZERO(PCI_HC_MAIN_IRQ_MASK_OFS);
2387 ZERO(MV_PCI_SERR_MASK); 2411 ZERO(MV_PCI_SERR_MASK);
2388 ZERO(hpriv->irq_cause_ofs); 2412 ZERO(hpriv->irq_cause_ofs);
2389 ZERO(hpriv->irq_mask_ofs); 2413 ZERO(hpriv->irq_mask_ofs);
@@ -2755,32 +2779,18 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
2755 2779
2756static void mv_eh_freeze(struct ata_port *ap) 2780static void mv_eh_freeze(struct ata_port *ap)
2757{ 2781{
2758 struct mv_host_priv *hpriv = ap->host->private_data;
2759 unsigned int shift, hardport, port = ap->port_no;
2760 u32 main_irq_mask;
2761
2762 /* FIXME: handle coalescing completion events properly */
2763
2764 mv_stop_edma(ap); 2782 mv_stop_edma(ap);
2765 MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport); 2783 mv_enable_port_irqs(ap, 0);
2766
2767 /* disable assertion of portN err, done events */
2768 main_irq_mask = readl(hpriv->main_irq_mask_addr);
2769 main_irq_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
2770 writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
2771} 2784}
2772 2785
2773static void mv_eh_thaw(struct ata_port *ap) 2786static void mv_eh_thaw(struct ata_port *ap)
2774{ 2787{
2775 struct mv_host_priv *hpriv = ap->host->private_data; 2788 struct mv_host_priv *hpriv = ap->host->private_data;
2776 unsigned int shift, hardport, port = ap->port_no; 2789 unsigned int port = ap->port_no;
2790 unsigned int hardport = mv_hardport_from_port(port);
2777 void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port); 2791 void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
2778 void __iomem *port_mmio = mv_ap_base(ap); 2792 void __iomem *port_mmio = mv_ap_base(ap);
2779 u32 main_irq_mask, hc_irq_cause; 2793 u32 hc_irq_cause;
2780
2781 /* FIXME: handle coalescing completion events properly */
2782
2783 MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
2784 2794
2785 /* clear EDMA errors on this port */ 2795 /* clear EDMA errors on this port */
2786 writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 2796 writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
@@ -2790,10 +2800,7 @@ static void mv_eh_thaw(struct ata_port *ap)
2790 hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport); 2800 hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport);
2791 writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); 2801 writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
2792 2802
2793 /* enable assertion of portN err, done events */ 2803 mv_enable_port_irqs(ap, DONE_IRQ | ERR_IRQ);
2794 main_irq_mask = readl(hpriv->main_irq_mask_addr);
2795 main_irq_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
2796 writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
2797} 2804}
2798 2805
2799/** 2806/**
@@ -3046,7 +3053,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
3046 } 3053 }
3047 3054
3048 /* global interrupt mask: 0 == mask everything */ 3055 /* global interrupt mask: 0 == mask everything */
3049 writel(0, hpriv->main_irq_mask_addr); 3056 mv_set_main_irq_mask(host, ~0, 0);
3050 3057
3051 n_hc = mv_get_hc_count(host->ports[0]->flags); 3058 n_hc = mv_get_hc_count(host->ports[0]->flags);
3052 3059
@@ -3099,7 +3106,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
3099 * enable only global host interrupts for now. 3106 * enable only global host interrupts for now.
3100 * The per-port interrupts get done later as ports are set up. 3107 * The per-port interrupts get done later as ports are set up.
3101 */ 3108 */
3102 writelfl(PCI_ERR, hpriv->main_irq_mask_addr); 3109 mv_set_main_irq_mask(host, 0, PCI_ERR);
3103 } 3110 }
3104done: 3111done:
3105 return rc; 3112 return rc;