aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-01-23 14:19:32 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-01-23 14:19:32 -0500
commitd227e87e6c939c6071def92bc7691ad774c733ff (patch)
tree31fbc74974da765322b26de321e0b33f2f7e1478 /arch
parentf66d45e99eb7ca91822c3e3f6d7a98843c9626cb (diff)
parent364ca8a897eadb2f0e76b7f0ffe94168f6d83d66 (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: [MIPS] Vr41xx: Fix after GENERIC_HARDIRQS_NO__DO_IRQ change [MIPS] SMTC: Instant IPI replay.
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig14
-rw-r--r--arch/mips/kernel/smtc.c54
-rw-r--r--arch/mips/vr41xx/common/irq.c12
3 files changed, 56 insertions, 24 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fd2ff0698a85..bbd386f572d9 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1568,6 +1568,20 @@ config MIPS_MT_FPAFF
1568 depends on MIPS_MT 1568 depends on MIPS_MT
1569 default y 1569 default y
1570 1570
1571config MIPS_MT_SMTC_INSTANT_REPLAY
1572 bool "Low-latency Dispatch of Deferred SMTC IPIs"
1573 depends on MIPS_MT_SMTC
1574 default y
1575 help
1576 SMTC pseudo-interrupts between TCs are deferred and queued
1577 if the target TC is interrupt-inhibited (IXMT). In the first
1578 SMTC prototypes, these queued IPIs were serviced on return
1579 to user mode, or on entry into the kernel idle loop. The
1580 INSTANT_REPLAY option dispatches them as part of local_irq_restore()
1581 processing, which adds runtime overhead (hence the option to turn
1582 it off), but ensures that IPIs are handled promptly even under
1583 heavy I/O interrupt load.
1584
1571config MIPS_VPE_LOADER_TOM 1585config MIPS_VPE_LOADER_TOM
1572 bool "Load VPE program into memory hidden from linux" 1586 bool "Load VPE program into memory hidden from linux"
1573 depends on MIPS_VPE_LOADER 1587 depends on MIPS_VPE_LOADER
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index a8b387197d5b..44238ab2fc99 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1017,6 +1017,33 @@ void setup_cross_vpe_interrupts(void)
1017 * SMTC-specific hacks invoked from elsewhere in the kernel. 1017 * SMTC-specific hacks invoked from elsewhere in the kernel.
1018 */ 1018 */
1019 1019
1020void smtc_ipi_replay(void)
1021{
1022 /*
1023 * To the extent that we've ever turned interrupts off,
1024 * we may have accumulated deferred IPIs. This is subtle.
1025 * If we use the smtc_ipi_qdepth() macro, we'll get an
1026 * exact number - but we'll also disable interrupts
1027 * and create a window of failure where a new IPI gets
1028 * queued after we test the depth but before we re-enable
1029 * interrupts. So long as IXMT never gets set, however,
1030 * we should be OK: If we pick up something and dispatch
1031 * it here, that's great. If we see nothing, but concurrent
1032 * with this operation, another TC sends us an IPI, IXMT
1033 * is clear, and we'll handle it as a real pseudo-interrupt
1034 * and not a pseudo-pseudo interrupt.
1035 */
1036 if (IPIQ[smp_processor_id()].depth > 0) {
1037 struct smtc_ipi *pipi;
1038 extern void self_ipi(struct smtc_ipi *);
1039
1040 while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) {
1041 self_ipi(pipi);
1042 smtc_cpu_stats[smp_processor_id()].selfipis++;
1043 }
1044 }
1045}
1046
1020void smtc_idle_loop_hook(void) 1047void smtc_idle_loop_hook(void)
1021{ 1048{
1022#ifdef SMTC_IDLE_HOOK_DEBUG 1049#ifdef SMTC_IDLE_HOOK_DEBUG
@@ -1113,29 +1140,14 @@ void smtc_idle_loop_hook(void)
1113 if (pdb_msg != &id_ho_db_msg[0]) 1140 if (pdb_msg != &id_ho_db_msg[0])
1114 printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); 1141 printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
1115#endif /* SMTC_IDLE_HOOK_DEBUG */ 1142#endif /* SMTC_IDLE_HOOK_DEBUG */
1143
1116 /* 1144 /*
1117 * To the extent that we've ever turned interrupts off, 1145 * Replay any accumulated deferred IPIs. If "Instant Replay"
1118 * we may have accumulated deferred IPIs. This is subtle. 1146 * is in use, there should never be any.
1119 * If we use the smtc_ipi_qdepth() macro, we'll get an
1120 * exact number - but we'll also disable interrupts
1121 * and create a window of failure where a new IPI gets
1122 * queued after we test the depth but before we re-enable
1123 * interrupts. So long as IXMT never gets set, however,
1124 * we should be OK: If we pick up something and dispatch
1125 * it here, that's great. If we see nothing, but concurrent
1126 * with this operation, another TC sends us an IPI, IXMT
1127 * is clear, and we'll handle it as a real pseudo-interrupt
1128 * and not a pseudo-pseudo interrupt.
1129 */ 1147 */
1130 if (IPIQ[smp_processor_id()].depth > 0) { 1148#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
1131 struct smtc_ipi *pipi; 1149 smtc_ipi_replay();
1132 extern void self_ipi(struct smtc_ipi *); 1150#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
1133
1134 if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) {
1135 self_ipi(pipi);
1136 smtc_cpu_stats[smp_processor_id()].selfipis++;
1137 }
1138 }
1139} 1151}
1140 1152
1141void smtc_soft_dump(void) 1153void smtc_soft_dump(void)
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 397ba94cd7ec..16decf4ac2f4 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Interrupt handing routines for NEC VR4100 series. 2 * Interrupt handing routines for NEC VR4100 series.
3 * 3 *
4 * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 4 * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -73,13 +73,19 @@ static void irq_dispatch(unsigned int irq)
73 if (cascade->get_irq != NULL) { 73 if (cascade->get_irq != NULL) {
74 unsigned int source_irq = irq; 74 unsigned int source_irq = irq;
75 desc = irq_desc + source_irq; 75 desc = irq_desc + source_irq;
76 desc->chip->ack(source_irq); 76 if (desc->chip->mask_ack)
77 desc->chip->mask_ack(source_irq);
78 else {
79 desc->chip->mask(source_irq);
80 desc->chip->ack(source_irq);
81 }
77 irq = cascade->get_irq(irq); 82 irq = cascade->get_irq(irq);
78 if (irq < 0) 83 if (irq < 0)
79 atomic_inc(&irq_err_count); 84 atomic_inc(&irq_err_count);
80 else 85 else
81 irq_dispatch(irq); 86 irq_dispatch(irq);
82 desc->chip->end(source_irq); 87 if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
88 desc->chip->unmask(source_irq);
83 } else 89 } else
84 do_IRQ(irq); 90 do_IRQ(irq);
85} 91}