diff options
author | Mark Lord <liml@rtr.ca> | 2008-05-17 13:35:21 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-19 17:29:10 -0400 |
commit | c4de573b14d78ac83861d81d12977457d1e9cb6d (patch) | |
tree | 8831b6e4665649b8b3bd6a05dde1b032a0f0d6ce /drivers | |
parent | 51de32d200b21333950abc52ea1e589bc4eecef7 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_mv.c | 57 |
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 | ||
840 | static 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 | |||
852 | static 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 | ||
2756 | static void mv_eh_freeze(struct ata_port *ap) | 2780 | static 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 | ||
2773 | static void mv_eh_thaw(struct ata_port *ap) | 2786 | static 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 | } |
3104 | done: | 3111 | done: |
3105 | return rc; | 3112 | return rc; |