aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/entry.S6
-rw-r--r--arch/mips/kernel/genex.S31
-rw-r--r--arch/mips/kernel/smtc.c65
3 files changed, 89 insertions, 13 deletions
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 0b78fcbf044a..686249c5c328 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -121,7 +121,11 @@ FEXPORT(restore_partial) # restore partial frame
121 SAVE_AT 121 SAVE_AT
122 SAVE_TEMP 122 SAVE_TEMP
123 LONG_L v0, PT_STATUS(sp) 123 LONG_L v0, PT_STATUS(sp)
124 and v0, 1 124#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
125 and v0, ST0_IEP
126#else
127 and v0, ST0_IE
128#endif
125 beqz v0, 1f 129 beqz v0, 1f
126 jal trace_hardirqs_on 130 jal trace_hardirqs_on
127 b 2f 131 b 2f
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 83843a229be7..297bd56c2347 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -128,6 +128,37 @@ handle_vcei:
128 128
129 .align 5 129 .align 5
130NESTED(handle_int, PT_SIZE, sp) 130NESTED(handle_int, PT_SIZE, sp)
131#ifdef CONFIG_TRACE_IRQFLAGS
132 /*
133 * Check to see if the interrupted code has just disabled
134 * interrupts and ignore this interrupt for now if so.
135 *
136 * local_irq_disable() disables interrupts and then calls
137 * trace_hardirqs_off() to track the state. If an interrupt is taken
138 * after interrupts are disabled but before the state is updated
139 * it will appear to restore_all that it is incorrectly returning with
140 * interrupts disabled
141 */
142 .set push
143 .set noat
144 mfc0 k0, CP0_STATUS
145#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
146 and k0, ST0_IEP
147 bnez k0, 1f
148
149 mfc0 k0, EP0_EPC
150 .set noreorder
151 j k0
152 rfe
153#else
154 and k0, ST0_IE
155 bnez k0, 1f
156
157 eret
158#endif
1591:
160 .set pop
161#endif
131 SAVE_ALL 162 SAVE_ALL
132 CLI 163 CLI
133 TRACE_IRQS_OFF 164 TRACE_IRQS_OFF
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index f253eda27fa3..5dcfab6b288e 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/kernel_stat.h>
7#include <linux/module.h> 8#include <linux/module.h>
8 9
9#include <asm/cpu.h> 10#include <asm/cpu.h>
@@ -14,6 +15,7 @@
14#include <asm/hazards.h> 15#include <asm/hazards.h>
15#include <asm/mmu_context.h> 16#include <asm/mmu_context.h>
16#include <asm/smp.h> 17#include <asm/smp.h>
18#include <asm/mips-boards/maltaint.h>
17#include <asm/mipsregs.h> 19#include <asm/mipsregs.h>
18#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
19#include <asm/time.h> 21#include <asm/time.h>
@@ -75,7 +77,7 @@ static struct smtc_ipi_q freeIPIq;
75 77
76void ipi_decode(struct smtc_ipi *); 78void ipi_decode(struct smtc_ipi *);
77static void post_direct_ipi(int cpu, struct smtc_ipi *pipi); 79static void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
78static void setup_cross_vpe_interrupts(void); 80static void setup_cross_vpe_interrupts(unsigned int nvpe);
79void init_smtc_stats(void); 81void init_smtc_stats(void);
80 82
81/* Global SMTC Status */ 83/* Global SMTC Status */
@@ -168,7 +170,10 @@ __setup("tintq=", tintq);
168 170
169int imstuckcount[2][8]; 171int imstuckcount[2][8];
170/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ 172/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */
171int vpemask[2][8] = {{0,1,1,0,0,0,0,1},{0,1,0,0,0,0,0,1}}; 173int vpemask[2][8] = {
174 {0, 0, 1, 0, 0, 0, 0, 1},
175 {0, 0, 0, 0, 0, 0, 0, 1}
176};
172int tcnoprog[NR_CPUS]; 177int tcnoprog[NR_CPUS];
173static atomic_t idle_hook_initialized = {0}; 178static atomic_t idle_hook_initialized = {0};
174static int clock_hang_reported[NR_CPUS]; 179static int clock_hang_reported[NR_CPUS];
@@ -501,8 +506,7 @@ void mipsmt_prepare_cpus(void)
501 506
502 /* If we have multiple VPEs running, set up the cross-VPE interrupt */ 507 /* If we have multiple VPEs running, set up the cross-VPE interrupt */
503 508
504 if (nvpe > 1) 509 setup_cross_vpe_interrupts(nvpe);
505 setup_cross_vpe_interrupts();
506 510
507 /* Set up queue of free IPI "messages". */ 511 /* Set up queue of free IPI "messages". */
508 nipi = NR_CPUS * IPIBUF_PER_CPU; 512 nipi = NR_CPUS * IPIBUF_PER_CPU;
@@ -607,7 +611,12 @@ void smtc_cpus_done(void)
607int setup_irq_smtc(unsigned int irq, struct irqaction * new, 611int setup_irq_smtc(unsigned int irq, struct irqaction * new,
608 unsigned long hwmask) 612 unsigned long hwmask)
609{ 613{
614 unsigned int vpe = current_cpu_data.vpe_id;
615
610 irq_hwmask[irq] = hwmask; 616 irq_hwmask[irq] = hwmask;
617#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
618 vpemask[vpe][irq - MIPSCPU_INT_BASE] = 1;
619#endif
611 620
612 return setup_irq(irq, new); 621 return setup_irq(irq, new);
613} 622}
@@ -812,12 +821,15 @@ void ipi_decode(struct smtc_ipi *pipi)
812 smtc_ipi_nq(&freeIPIq, pipi); 821 smtc_ipi_nq(&freeIPIq, pipi);
813 switch (type_copy) { 822 switch (type_copy) {
814 case SMTC_CLOCK_TICK: 823 case SMTC_CLOCK_TICK:
824 irq_enter();
825 kstat_this_cpu.irqs[MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR]++;
815 /* Invoke Clock "Interrupt" */ 826 /* Invoke Clock "Interrupt" */
816 ipi_timer_latch[dest_copy] = 0; 827 ipi_timer_latch[dest_copy] = 0;
817#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG 828#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
818 clock_hang_reported[dest_copy] = 0; 829 clock_hang_reported[dest_copy] = 0;
819#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ 830#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
820 local_timer_interrupt(0, NULL); 831 local_timer_interrupt(0, NULL);
832 irq_exit();
821 break; 833 break;
822 case LINUX_SMP_IPI: 834 case LINUX_SMP_IPI:
823 switch ((int)arg_copy) { 835 switch ((int)arg_copy) {
@@ -965,8 +977,11 @@ static void ipi_irq_dispatch(void)
965 977
966static struct irqaction irq_ipi; 978static struct irqaction irq_ipi;
967 979
968static void setup_cross_vpe_interrupts(void) 980static void setup_cross_vpe_interrupts(unsigned int nvpe)
969{ 981{
982 if (nvpe < 1)
983 return;
984
970 if (!cpu_has_vint) 985 if (!cpu_has_vint)
971 panic("SMTC Kernel requires Vectored Interupt support"); 986 panic("SMTC Kernel requires Vectored Interupt support");
972 987
@@ -984,10 +999,17 @@ static void setup_cross_vpe_interrupts(void)
984 999
985/* 1000/*
986 * 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().
987 */ 1007 */
988 1008
989void smtc_ipi_replay(void) 1009static void __smtc_ipi_replay(void)
990{ 1010{
1011 unsigned int cpu = smp_processor_id();
1012
991 /* 1013 /*
992 * To the extent that we've ever turned interrupts off, 1014 * To the extent that we've ever turned interrupts off,
993 * we may have accumulated deferred IPIs. This is subtle. 1015 * we may have accumulated deferred IPIs. This is subtle.
@@ -1002,17 +1024,30 @@ void smtc_ipi_replay(void)
1002 * 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
1003 * and not a pseudo-pseudo interrupt. 1025 * and not a pseudo-pseudo interrupt.
1004 */ 1026 */
1005 if (IPIQ[smp_processor_id()].depth > 0) { 1027 if (IPIQ[cpu].depth > 0) {
1006 struct smtc_ipi *pipi; 1028 while (1) {
1007 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;
1008 1038
1009 while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) {
1010 self_ipi(pipi); 1039 self_ipi(pipi);
1011 smtc_cpu_stats[smp_processor_id()].selfipis++; 1040 smtc_cpu_stats[cpu].selfipis++;
1012 } 1041 }
1013 } 1042 }
1014} 1043}
1015 1044
1045void smtc_ipi_replay(void)
1046{
1047 raw_local_irq_disable();
1048 __smtc_ipi_replay();
1049}
1050
1016EXPORT_SYMBOL(smtc_ipi_replay); 1051EXPORT_SYMBOL(smtc_ipi_replay);
1017 1052
1018void smtc_idle_loop_hook(void) 1053void smtc_idle_loop_hook(void)
@@ -1117,7 +1152,13 @@ void smtc_idle_loop_hook(void)
1117 * is in use, there should never be any. 1152 * is in use, there should never be any.
1118 */ 1153 */
1119#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY 1154#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
1120 smtc_ipi_replay(); 1155 {
1156 unsigned long flags;
1157
1158 local_irq_save(flags);
1159 __smtc_ipi_replay();
1160 local_irq_restore(flags);
1161 }
1121#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ 1162#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
1122} 1163}
1123 1164