diff options
Diffstat (limited to 'arch/mips/kernel/smtc.c')
-rw-r--r-- | arch/mips/kernel/smtc.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a8b387197d5b..6a857bf030b0 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
5 | #include <linux/cpumask.h> | 5 | #include <linux/cpumask.h> |
6 | #include <linux/interrupt.h> | 6 | #include <linux/interrupt.h> |
7 | #include <linux/module.h> | ||
7 | 8 | ||
8 | #include <asm/cpu.h> | 9 | #include <asm/cpu.h> |
9 | #include <asm/processor.h> | 10 | #include <asm/processor.h> |
@@ -270,9 +271,12 @@ void smtc_configure_tlb(void) | |||
270 | * of their initialization in smtc_cpu_setup(). | 271 | * of their initialization in smtc_cpu_setup(). |
271 | */ | 272 | */ |
272 | 273 | ||
273 | tlbsiz = tlbsiz & 0x3f; /* MIPS32 limits TLB indices to 64 */ | 274 | /* MIPS32 limits TLB indices to 64 */ |
274 | cpu_data[0].tlbsize = tlbsiz; | 275 | if (tlbsiz > 64) |
276 | tlbsiz = 64; | ||
277 | cpu_data[0].tlbsize = current_cpu_data.tlbsize = tlbsiz; | ||
275 | smtc_status |= SMTC_TLB_SHARED; | 278 | smtc_status |= SMTC_TLB_SHARED; |
279 | local_flush_tlb_all(); | ||
276 | 280 | ||
277 | printk("TLB of %d entry pairs shared by %d VPEs\n", | 281 | printk("TLB of %d entry pairs shared by %d VPEs\n", |
278 | tlbsiz, vpes); | 282 | tlbsiz, vpes); |
@@ -1017,6 +1021,35 @@ void setup_cross_vpe_interrupts(void) | |||
1017 | * SMTC-specific hacks invoked from elsewhere in the kernel. | 1021 | * SMTC-specific hacks invoked from elsewhere in the kernel. |
1018 | */ | 1022 | */ |
1019 | 1023 | ||
1024 | void smtc_ipi_replay(void) | ||
1025 | { | ||
1026 | /* | ||
1027 | * To the extent that we've ever turned interrupts off, | ||
1028 | * we may have accumulated deferred IPIs. This is subtle. | ||
1029 | * If we use the smtc_ipi_qdepth() macro, we'll get an | ||
1030 | * exact number - but we'll also disable interrupts | ||
1031 | * and create a window of failure where a new IPI gets | ||
1032 | * queued after we test the depth but before we re-enable | ||
1033 | * interrupts. So long as IXMT never gets set, however, | ||
1034 | * we should be OK: If we pick up something and dispatch | ||
1035 | * it here, that's great. If we see nothing, but concurrent | ||
1036 | * with this operation, another TC sends us an IPI, IXMT | ||
1037 | * is clear, and we'll handle it as a real pseudo-interrupt | ||
1038 | * and not a pseudo-pseudo interrupt. | ||
1039 | */ | ||
1040 | if (IPIQ[smp_processor_id()].depth > 0) { | ||
1041 | struct smtc_ipi *pipi; | ||
1042 | extern void self_ipi(struct smtc_ipi *); | ||
1043 | |||
1044 | while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) { | ||
1045 | self_ipi(pipi); | ||
1046 | smtc_cpu_stats[smp_processor_id()].selfipis++; | ||
1047 | } | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | EXPORT_SYMBOL(smtc_ipi_replay); | ||
1052 | |||
1020 | void smtc_idle_loop_hook(void) | 1053 | void smtc_idle_loop_hook(void) |
1021 | { | 1054 | { |
1022 | #ifdef SMTC_IDLE_HOOK_DEBUG | 1055 | #ifdef SMTC_IDLE_HOOK_DEBUG |
@@ -1113,29 +1146,14 @@ void smtc_idle_loop_hook(void) | |||
1113 | if (pdb_msg != &id_ho_db_msg[0]) | 1146 | if (pdb_msg != &id_ho_db_msg[0]) |
1114 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); | 1147 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); |
1115 | #endif /* SMTC_IDLE_HOOK_DEBUG */ | 1148 | #endif /* SMTC_IDLE_HOOK_DEBUG */ |
1149 | |||
1116 | /* | 1150 | /* |
1117 | * To the extent that we've ever turned interrupts off, | 1151 | * Replay any accumulated deferred IPIs. If "Instant Replay" |
1118 | * we may have accumulated deferred IPIs. This is subtle. | 1152 | * 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 | */ | 1153 | */ |
1130 | if (IPIQ[smp_processor_id()].depth > 0) { | 1154 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY |
1131 | struct smtc_ipi *pipi; | 1155 | smtc_ipi_replay(); |
1132 | extern void self_ipi(struct smtc_ipi *); | 1156 | #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 | } | 1157 | } |
1140 | 1158 | ||
1141 | void smtc_soft_dump(void) | 1159 | void smtc_soft_dump(void) |