diff options
author | David Daney <ddaney@caviumnetworks.com> | 2010-02-15 12:13:18 -0800 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-02-27 12:53:29 +0100 |
commit | 86568dc41e8c7edcf6d014a64d143536d24b6a5d (patch) | |
tree | bc4ef4144c20ca419f19d3e044fb86babfb33959 | |
parent | f8c2648666b5a1b5ba9bbb662ae569bafd3cc830 (diff) |
MIPS: Octeon: Do proper acknowledgment of CIU timer interrupts.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
To: linux-mips@linux-mips.org
To: netdev@vger.kernel.org
To: gregkh@suse.de
Patchwork: http://patchwork.linux-mips.org/patch/967/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 67 |
1 files changed, 63 insertions, 4 deletions
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 1460d0836dc..0bc79dcede2 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -51,9 +51,6 @@ static void octeon_irq_core_eoi(unsigned int irq) */ if (desc->status & IRQ_DISABLED) return; - - /* There is a race here. We should fix it. */ - /* * We don't need to disable IRQs to make these atomic since * they are already disabled earlier in the low level @@ -202,6 +199,29 @@ static void octeon_irq_ciu0_ack_v2(unsigned int irq) } /* + * CIU timer type interrupts must be acknoleged by writing a '1' bit + * to their sum0 bit. + */ +static void octeon_irq_ciu0_timer_ack(unsigned int irq) +{ + int index = cvmx_get_core_num() * 2; + uint64_t mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); +} + +static void octeon_irq_ciu0_timer_ack_v1(unsigned int irq) +{ + octeon_irq_ciu0_timer_ack(irq); + octeon_irq_ciu0_ack(irq); +} + +static void octeon_irq_ciu0_timer_ack_v2(unsigned int irq) +{ + octeon_irq_ciu0_timer_ack(irq); + octeon_irq_ciu0_ack_v2(irq); +} + +/* * Enable the irq on the current core for chips that have the EN*_W1{S,C} * registers. */ @@ -304,6 +324,28 @@ static struct irq_chip octeon_irq_chip_ciu0 = { #endif }; +static struct irq_chip octeon_irq_chip_ciu0_timer_v2 = { + .name = "CIU0-T", + .enable = octeon_irq_ciu0_enable_v2, + .disable = octeon_irq_ciu0_disable_all_v2, + .ack = octeon_irq_ciu0_timer_ack_v2, + .eoi = octeon_irq_ciu0_eoi_v2, +#ifdef CONFIG_SMP + .set_affinity = octeon_irq_ciu0_set_affinity_v2, +#endif +}; + +static struct irq_chip octeon_irq_chip_ciu0_timer = { + .name = "CIU0-T", + .enable = octeon_irq_ciu0_enable, + .disable = octeon_irq_ciu0_disable, + .ack = octeon_irq_ciu0_timer_ack_v1, + .eoi = octeon_irq_ciu0_eoi, +#ifdef CONFIG_SMP + .set_affinity = octeon_irq_ciu0_set_affinity, +#endif +}; + static void octeon_irq_ciu1_ack(unsigned int irq) { @@ -587,6 +629,7 @@ void __init arch_init_irq(void) { int irq; struct irq_chip *chip0; + struct irq_chip *chip0_timer; struct irq_chip *chip1; #ifdef CONFIG_SMP @@ -602,9 +645,11 @@ void __init arch_init_irq(void) OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { chip0 = &octeon_irq_chip_ciu0_v2; + chip0_timer = &octeon_irq_chip_ciu0_timer_v2; chip1 = &octeon_irq_chip_ciu1_v2; } else { chip0 = &octeon_irq_chip_ciu0; + chip0_timer = &octeon_irq_chip_ciu0_timer; chip1 = &octeon_irq_chip_ciu1; } @@ -618,7 +663,21 @@ void __init arch_init_irq(void) /* 24 - 87 CIU_INT_SUM0 */ for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { - set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); + switch (irq) { + case OCTEON_IRQ_GMX_DRP0: + case OCTEON_IRQ_GMX_DRP1: + case OCTEON_IRQ_IPD_DRP: + case OCTEON_IRQ_KEY_ZERO: + case OCTEON_IRQ_TIMER0: + case OCTEON_IRQ_TIMER1: + case OCTEON_IRQ_TIMER2: + case OCTEON_IRQ_TIMER3: + set_irq_chip_and_handler(irq, chip0_timer, handle_percpu_irq); + break; + default: + set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); + break; + } } /* 88 - 151 CIU_INT_SUM1 */ |