aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/Kconfig14
-rw-r--r--arch/mips/kernel/smtc.c54
-rw-r--r--include/asm-mips/irqflags.h22
3 files changed, 69 insertions, 21 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/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h
index 46bf5de5ac72..af3b07dfad4b 100644
--- a/include/asm-mips/irqflags.h
+++ b/include/asm-mips/irqflags.h
@@ -15,6 +15,27 @@
15 15
16#include <asm/hazards.h> 16#include <asm/hazards.h>
17 17
18/*
19 * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred IPIs,
20 * at the cost of branch and call overhead on each local_irq_restore()
21 */
22
23#ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
24
25extern void smtc_ipi_replay(void);
26
27#define irq_restore_epilog(flags) \
28do { \
29 if (!(flags & 0x0400)) \
30 smtc_ipi_replay(); \
31} while (0)
32
33#else
34
35#define irq_restore_epilog(ignore) do { } while (0)
36
37#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
38
18__asm__ ( 39__asm__ (
19 " .macro raw_local_irq_enable \n" 40 " .macro raw_local_irq_enable \n"
20 " .set push \n" 41 " .set push \n"
@@ -193,6 +214,7 @@ do { \
193 : "=r" (__tmp1) \ 214 : "=r" (__tmp1) \
194 : "0" (flags) \ 215 : "0" (flags) \
195 : "memory"); \ 216 : "memory"); \
217 irq_restore_epilog(flags); \
196} while(0) 218} while(0)
197 219
198static inline int raw_irqs_disabled_flags(unsigned long flags) 220static inline int raw_irqs_disabled_flags(unsigned long flags)