diff options
Diffstat (limited to 'arch/mips/kernel/smtc.c')
-rw-r--r-- | arch/mips/kernel/smtc.c | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 802febed7df5..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> |
@@ -261,6 +262,7 @@ void smtc_configure_tlb(void) | |||
261 | } | 262 | } |
262 | } | 263 | } |
263 | write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB); | 264 | write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB); |
265 | ehb(); | ||
264 | 266 | ||
265 | /* | 267 | /* |
266 | * Setup kernel data structures to use software total, | 268 | * Setup kernel data structures to use software total, |
@@ -269,9 +271,12 @@ void smtc_configure_tlb(void) | |||
269 | * of their initialization in smtc_cpu_setup(). | 271 | * of their initialization in smtc_cpu_setup(). |
270 | */ | 272 | */ |
271 | 273 | ||
272 | tlbsiz = tlbsiz & 0x3f; /* MIPS32 limits TLB indices to 64 */ | 274 | /* MIPS32 limits TLB indices to 64 */ |
273 | cpu_data[0].tlbsize = tlbsiz; | 275 | if (tlbsiz > 64) |
276 | tlbsiz = 64; | ||
277 | cpu_data[0].tlbsize = current_cpu_data.tlbsize = tlbsiz; | ||
274 | smtc_status |= SMTC_TLB_SHARED; | 278 | smtc_status |= SMTC_TLB_SHARED; |
279 | local_flush_tlb_all(); | ||
275 | 280 | ||
276 | printk("TLB of %d entry pairs shared by %d VPEs\n", | 281 | printk("TLB of %d entry pairs shared by %d VPEs\n", |
277 | tlbsiz, vpes); | 282 | tlbsiz, vpes); |
@@ -1016,6 +1021,35 @@ void setup_cross_vpe_interrupts(void) | |||
1016 | * SMTC-specific hacks invoked from elsewhere in the kernel. | 1021 | * SMTC-specific hacks invoked from elsewhere in the kernel. |
1017 | */ | 1022 | */ |
1018 | 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 | |||
1019 | void smtc_idle_loop_hook(void) | 1053 | void smtc_idle_loop_hook(void) |
1020 | { | 1054 | { |
1021 | #ifdef SMTC_IDLE_HOOK_DEBUG | 1055 | #ifdef SMTC_IDLE_HOOK_DEBUG |
@@ -1112,29 +1146,14 @@ void smtc_idle_loop_hook(void) | |||
1112 | if (pdb_msg != &id_ho_db_msg[0]) | 1146 | if (pdb_msg != &id_ho_db_msg[0]) |
1113 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); | 1147 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); |
1114 | #endif /* SMTC_IDLE_HOOK_DEBUG */ | 1148 | #endif /* SMTC_IDLE_HOOK_DEBUG */ |
1149 | |||
1115 | /* | 1150 | /* |
1116 | * To the extent that we've ever turned interrupts off, | 1151 | * Replay any accumulated deferred IPIs. If "Instant Replay" |
1117 | * we may have accumulated deferred IPIs. This is subtle. | 1152 | * is in use, there should never be any. |
1118 | * If we use the smtc_ipi_qdepth() macro, we'll get an | ||
1119 | * exact number - but we'll also disable interrupts | ||
1120 | * and create a window of failure where a new IPI gets | ||
1121 | * queued after we test the depth but before we re-enable | ||
1122 | * interrupts. So long as IXMT never gets set, however, | ||
1123 | * we should be OK: If we pick up something and dispatch | ||
1124 | * it here, that's great. If we see nothing, but concurrent | ||
1125 | * with this operation, another TC sends us an IPI, IXMT | ||
1126 | * is clear, and we'll handle it as a real pseudo-interrupt | ||
1127 | * and not a pseudo-pseudo interrupt. | ||
1128 | */ | 1153 | */ |
1129 | if (IPIQ[smp_processor_id()].depth > 0) { | 1154 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY |
1130 | struct smtc_ipi *pipi; | 1155 | smtc_ipi_replay(); |
1131 | extern void self_ipi(struct smtc_ipi *); | 1156 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ |
1132 | |||
1133 | if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) { | ||
1134 | self_ipi(pipi); | ||
1135 | smtc_cpu_stats[smp_processor_id()].selfipis++; | ||
1136 | } | ||
1137 | } | ||
1138 | } | 1157 | } |
1139 | 1158 | ||
1140 | void smtc_soft_dump(void) | 1159 | void smtc_soft_dump(void) |