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 | |
| 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>
| -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; |
