diff options
Diffstat (limited to 'arch/mips')
| -rw-r--r-- | arch/mips/kernel/smtc.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index e50fe20571f0..5dcfab6b288e 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
| @@ -999,10 +999,17 @@ static void setup_cross_vpe_interrupts(unsigned int nvpe) | |||
| 999 | 999 | ||
| 1000 | /* | 1000 | /* |
| 1001 | * SMTC-specific hacks invoked from elsewhere in the kernel. | 1001 | * SMTC-specific hacks invoked from elsewhere in the kernel. |
| 1002 | * | ||
| 1003 | * smtc_ipi_replay is called from raw_local_irq_restore which is only ever | ||
| 1004 | * called with interrupts disabled. We do rely on interrupts being disabled | ||
| 1005 | * here because using spin_lock_irqsave()/spin_unlock_irqrestore() would | ||
| 1006 | * result in a recursive call to raw_local_irq_restore(). | ||
| 1002 | */ | 1007 | */ |
| 1003 | 1008 | ||
| 1004 | void smtc_ipi_replay(void) | 1009 | static void __smtc_ipi_replay(void) |
| 1005 | { | 1010 | { |
| 1011 | unsigned int cpu = smp_processor_id(); | ||
| 1012 | |||
| 1006 | /* | 1013 | /* |
| 1007 | * To the extent that we've ever turned interrupts off, | 1014 | * To the extent that we've ever turned interrupts off, |
| 1008 | * we may have accumulated deferred IPIs. This is subtle. | 1015 | * we may have accumulated deferred IPIs. This is subtle. |
| @@ -1017,17 +1024,30 @@ void smtc_ipi_replay(void) | |||
| 1017 | * is clear, and we'll handle it as a real pseudo-interrupt | 1024 | * is clear, and we'll handle it as a real pseudo-interrupt |
| 1018 | * and not a pseudo-pseudo interrupt. | 1025 | * and not a pseudo-pseudo interrupt. |
| 1019 | */ | 1026 | */ |
| 1020 | if (IPIQ[smp_processor_id()].depth > 0) { | 1027 | if (IPIQ[cpu].depth > 0) { |
| 1021 | struct smtc_ipi *pipi; | 1028 | while (1) { |
| 1022 | extern void self_ipi(struct smtc_ipi *); | 1029 | struct smtc_ipi_q *q = &IPIQ[cpu]; |
| 1030 | struct smtc_ipi *pipi; | ||
| 1031 | extern void self_ipi(struct smtc_ipi *); | ||
| 1032 | |||
| 1033 | spin_lock(&q->lock); | ||
| 1034 | pipi = __smtc_ipi_dq(q); | ||
| 1035 | spin_unlock(&q->lock); | ||
| 1036 | if (!pipi) | ||
| 1037 | break; | ||
| 1023 | 1038 | ||
| 1024 | while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) { | ||
| 1025 | self_ipi(pipi); | 1039 | self_ipi(pipi); |
| 1026 | smtc_cpu_stats[smp_processor_id()].selfipis++; | 1040 | smtc_cpu_stats[cpu].selfipis++; |
| 1027 | } | 1041 | } |
| 1028 | } | 1042 | } |
| 1029 | } | 1043 | } |
| 1030 | 1044 | ||
| 1045 | void smtc_ipi_replay(void) | ||
| 1046 | { | ||
| 1047 | raw_local_irq_disable(); | ||
| 1048 | __smtc_ipi_replay(); | ||
| 1049 | } | ||
| 1050 | |||
| 1031 | EXPORT_SYMBOL(smtc_ipi_replay); | 1051 | EXPORT_SYMBOL(smtc_ipi_replay); |
| 1032 | 1052 | ||
| 1033 | void smtc_idle_loop_hook(void) | 1053 | void smtc_idle_loop_hook(void) |
| @@ -1132,7 +1152,13 @@ void smtc_idle_loop_hook(void) | |||
| 1132 | * is in use, there should never be any. | 1152 | * is in use, there should never be any. |
| 1133 | */ | 1153 | */ |
| 1134 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY | 1154 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY |
| 1135 | smtc_ipi_replay(); | 1155 | { |
| 1156 | unsigned long flags; | ||
| 1157 | |||
| 1158 | local_irq_save(flags); | ||
| 1159 | __smtc_ipi_replay(); | ||
| 1160 | local_irq_restore(flags); | ||
| 1161 | } | ||
| 1136 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ | 1162 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ |
| 1137 | } | 1163 | } |
| 1138 | 1164 | ||
