aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/cavium-octeon
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2010-02-15 15:13:18 -0500
committerRalf Baechle <ralf@linux-mips.org>2010-02-27 06:53:29 -0500
commit86568dc41e8c7edcf6d014a64d143536d24b6a5d (patch)
treebc4ef4144c20ca419f19d3e044fb86babfb33959 /arch/mips/cavium-octeon
parentf8c2648666b5a1b5ba9bbb662ae569bafd3cc830 (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>
Diffstat (limited to 'arch/mips/cavium-octeon')
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c67
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 1460d0836dc0..0bc79dcede26 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)
51 */ 51 */
52 if (desc->status & IRQ_DISABLED) 52 if (desc->status & IRQ_DISABLED)
53 return; 53 return;
54
55 /* There is a race here. We should fix it. */
56
57 /* 54 /*
58 * We don't need to disable IRQs to make these atomic since 55 * We don't need to disable IRQs to make these atomic since
59 * they are already disabled earlier in the low level 56 * they are already disabled earlier in the low level
@@ -202,6 +199,29 @@ static void octeon_irq_ciu0_ack_v2(unsigned int irq)
202} 199}
203 200
204/* 201/*
202 * CIU timer type interrupts must be acknoleged by writing a '1' bit
203 * to their sum0 bit.
204 */
205static void octeon_irq_ciu0_timer_ack(unsigned int irq)
206{
207 int index = cvmx_get_core_num() * 2;
208 uint64_t mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
209 cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask);
210}
211
212static void octeon_irq_ciu0_timer_ack_v1(unsigned int irq)
213{
214 octeon_irq_ciu0_timer_ack(irq);
215 octeon_irq_ciu0_ack(irq);
216}
217
218static void octeon_irq_ciu0_timer_ack_v2(unsigned int irq)
219{
220 octeon_irq_ciu0_timer_ack(irq);
221 octeon_irq_ciu0_ack_v2(irq);
222}
223
224/*
205 * Enable the irq on the current core for chips that have the EN*_W1{S,C} 225 * Enable the irq on the current core for chips that have the EN*_W1{S,C}
206 * registers. 226 * registers.
207 */ 227 */
@@ -304,6 +324,28 @@ static struct irq_chip octeon_irq_chip_ciu0 = {
304#endif 324#endif
305}; 325};
306 326
327static struct irq_chip octeon_irq_chip_ciu0_timer_v2 = {
328 .name = "CIU0-T",
329 .enable = octeon_irq_ciu0_enable_v2,
330 .disable = octeon_irq_ciu0_disable_all_v2,
331 .ack = octeon_irq_ciu0_timer_ack_v2,
332 .eoi = octeon_irq_ciu0_eoi_v2,
333#ifdef CONFIG_SMP
334 .set_affinity = octeon_irq_ciu0_set_affinity_v2,
335#endif
336};
337
338static struct irq_chip octeon_irq_chip_ciu0_timer = {
339 .name = "CIU0-T",
340 .enable = octeon_irq_ciu0_enable,
341 .disable = octeon_irq_ciu0_disable,
342 .ack = octeon_irq_ciu0_timer_ack_v1,
343 .eoi = octeon_irq_ciu0_eoi,
344#ifdef CONFIG_SMP
345 .set_affinity = octeon_irq_ciu0_set_affinity,
346#endif
347};
348
307 349
308static void octeon_irq_ciu1_ack(unsigned int irq) 350static void octeon_irq_ciu1_ack(unsigned int irq)
309{ 351{
@@ -587,6 +629,7 @@ void __init arch_init_irq(void)
587{ 629{
588 int irq; 630 int irq;
589 struct irq_chip *chip0; 631 struct irq_chip *chip0;
632 struct irq_chip *chip0_timer;
590 struct irq_chip *chip1; 633 struct irq_chip *chip1;
591 634
592#ifdef CONFIG_SMP 635#ifdef CONFIG_SMP
@@ -602,9 +645,11 @@ void __init arch_init_irq(void)
602 OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || 645 OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
603 OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { 646 OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
604 chip0 = &octeon_irq_chip_ciu0_v2; 647 chip0 = &octeon_irq_chip_ciu0_v2;
648 chip0_timer = &octeon_irq_chip_ciu0_timer_v2;
605 chip1 = &octeon_irq_chip_ciu1_v2; 649 chip1 = &octeon_irq_chip_ciu1_v2;
606 } else { 650 } else {
607 chip0 = &octeon_irq_chip_ciu0; 651 chip0 = &octeon_irq_chip_ciu0;
652 chip0_timer = &octeon_irq_chip_ciu0_timer;
608 chip1 = &octeon_irq_chip_ciu1; 653 chip1 = &octeon_irq_chip_ciu1;
609 } 654 }
610 655
@@ -618,7 +663,21 @@ void __init arch_init_irq(void)
618 663
619 /* 24 - 87 CIU_INT_SUM0 */ 664 /* 24 - 87 CIU_INT_SUM0 */
620 for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { 665 for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
621 set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); 666 switch (irq) {
667 case OCTEON_IRQ_GMX_DRP0:
668 case OCTEON_IRQ_GMX_DRP1:
669 case OCTEON_IRQ_IPD_DRP:
670 case OCTEON_IRQ_KEY_ZERO:
671 case OCTEON_IRQ_TIMER0:
672 case OCTEON_IRQ_TIMER1:
673 case OCTEON_IRQ_TIMER2:
674 case OCTEON_IRQ_TIMER3:
675 set_irq_chip_and_handler(irq, chip0_timer, handle_percpu_irq);
676 break;
677 default:
678 set_irq_chip_and_handler(irq, chip0, handle_percpu_irq);
679 break;
680 }
622 } 681 }
623 682
624 /* 88 - 151 CIU_INT_SUM1 */ 683 /* 88 - 151 CIU_INT_SUM1 */