aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/smtc.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2007-05-01 00:24:54 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-05-01 00:24:54 -0400
commitbc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775 (patch)
tree427fcf2a7287c16d4b5aa6cbf494d59579a6a8b1 /arch/mips/kernel/smtc.c
parent3d29cdff999c37b3876082278a8134a0642a02cd (diff)
parentdc87c3985e9b442c60994308a96f887579addc39 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/usb/input/Makefile drivers/usb/input/gtco.c
Diffstat (limited to 'arch/mips/kernel/smtc.c')
-rw-r--r--arch/mips/kernel/smtc.c84
1 files changed, 61 insertions, 23 deletions
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 9251ea824937..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 */
@@ -141,10 +143,7 @@ __setup("ipibufs=", ipibufs);
141__setup("nostlb", stlb_disable); 143__setup("nostlb", stlb_disable);
142__setup("asidmask=", asidmask_set); 144__setup("asidmask=", asidmask_set);
143 145
144/* Enable additional debug checks before going into CPU idle loop */ 146#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
145#define SMTC_IDLE_HOOK_DEBUG
146
147#ifdef SMTC_IDLE_HOOK_DEBUG
148 147
149static int hang_trig = 0; 148static int hang_trig = 0;
150 149
@@ -171,12 +170,15 @@ __setup("tintq=", tintq);
171 170
172int imstuckcount[2][8]; 171int imstuckcount[2][8];
173/* 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 */
174int 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};
175int tcnoprog[NR_CPUS]; 177int tcnoprog[NR_CPUS];
176static atomic_t idle_hook_initialized = {0}; 178static atomic_t idle_hook_initialized = {0};
177static int clock_hang_reported[NR_CPUS]; 179static int clock_hang_reported[NR_CPUS];
178 180
179#endif /* SMTC_IDLE_HOOK_DEBUG */ 181#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
180 182
181/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */ 183/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
182 184
@@ -394,10 +396,10 @@ void mipsmt_prepare_cpus(void)
394 printk("ASID mask value override to 0x%x\n", asidmask); 396 printk("ASID mask value override to 0x%x\n", asidmask);
395 397
396 /* Temporary */ 398 /* Temporary */
397#ifdef SMTC_IDLE_HOOK_DEBUG 399#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
398 if (hang_trig) 400 if (hang_trig)
399 printk("Logic Analyser Trigger on suspected TC hang\n"); 401 printk("Logic Analyser Trigger on suspected TC hang\n");
400#endif /* SMTC_IDLE_HOOK_DEBUG */ 402#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
401 403
402 /* Put MVPE's into 'configuration state' */ 404 /* Put MVPE's into 'configuration state' */
403 write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC ); 405 write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC );
@@ -504,8 +506,7 @@ void mipsmt_prepare_cpus(void)
504 506
505 /* 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 */
506 508
507 if (nvpe > 1) 509 setup_cross_vpe_interrupts(nvpe);
508 setup_cross_vpe_interrupts();
509 510
510 /* Set up queue of free IPI "messages". */ 511 /* Set up queue of free IPI "messages". */
511 nipi = NR_CPUS * IPIBUF_PER_CPU; 512 nipi = NR_CPUS * IPIBUF_PER_CPU;
@@ -610,7 +611,12 @@ void smtc_cpus_done(void)
610int setup_irq_smtc(unsigned int irq, struct irqaction * new, 611int setup_irq_smtc(unsigned int irq, struct irqaction * new,
611 unsigned long hwmask) 612 unsigned long hwmask)
612{ 613{
614 unsigned int vpe = current_cpu_data.vpe_id;
615
613 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
614 620
615 return setup_irq(irq, new); 621 return setup_irq(irq, new);
616} 622}
@@ -815,12 +821,15 @@ void ipi_decode(struct smtc_ipi *pipi)
815 smtc_ipi_nq(&freeIPIq, pipi); 821 smtc_ipi_nq(&freeIPIq, pipi);
816 switch (type_copy) { 822 switch (type_copy) {
817 case SMTC_CLOCK_TICK: 823 case SMTC_CLOCK_TICK:
824 irq_enter();
825 kstat_this_cpu.irqs[MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR]++;
818 /* Invoke Clock "Interrupt" */ 826 /* Invoke Clock "Interrupt" */
819 ipi_timer_latch[dest_copy] = 0; 827 ipi_timer_latch[dest_copy] = 0;
820#ifdef SMTC_IDLE_HOOK_DEBUG 828#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
821 clock_hang_reported[dest_copy] = 0; 829 clock_hang_reported[dest_copy] = 0;
822#endif /* SMTC_IDLE_HOOK_DEBUG */ 830#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
823 local_timer_interrupt(0, NULL); 831 local_timer_interrupt(0, NULL);
832 irq_exit();
824 break; 833 break;
825 case LINUX_SMP_IPI: 834 case LINUX_SMP_IPI:
826 switch ((int)arg_copy) { 835 switch ((int)arg_copy) {
@@ -968,8 +977,11 @@ static void ipi_irq_dispatch(void)
968 977
969static struct irqaction irq_ipi; 978static struct irqaction irq_ipi;
970 979
971static void setup_cross_vpe_interrupts(void) 980static void setup_cross_vpe_interrupts(unsigned int nvpe)
972{ 981{
982 if (nvpe < 1)
983 return;
984
973 if (!cpu_has_vint) 985 if (!cpu_has_vint)
974 panic("SMTC Kernel requires Vectored Interupt support"); 986 panic("SMTC Kernel requires Vectored Interupt support");
975 987
@@ -987,10 +999,17 @@ static void setup_cross_vpe_interrupts(void)
987 999
988/* 1000/*
989 * 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().
990 */ 1007 */
991 1008
992void smtc_ipi_replay(void) 1009static void __smtc_ipi_replay(void)
993{ 1010{
1011 unsigned int cpu = smp_processor_id();
1012
994 /* 1013 /*
995 * To the extent that we've ever turned interrupts off, 1014 * To the extent that we've ever turned interrupts off,
996 * we may have accumulated deferred IPIs. This is subtle. 1015 * we may have accumulated deferred IPIs. This is subtle.
@@ -1005,22 +1024,35 @@ void smtc_ipi_replay(void)
1005 * 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
1006 * and not a pseudo-pseudo interrupt. 1025 * and not a pseudo-pseudo interrupt.
1007 */ 1026 */
1008 if (IPIQ[smp_processor_id()].depth > 0) { 1027 if (IPIQ[cpu].depth > 0) {
1009 struct smtc_ipi *pipi; 1028 while (1) {
1010 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;
1011 1038
1012 while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) {
1013 self_ipi(pipi); 1039 self_ipi(pipi);
1014 smtc_cpu_stats[smp_processor_id()].selfipis++; 1040 smtc_cpu_stats[cpu].selfipis++;
1015 } 1041 }
1016 } 1042 }
1017} 1043}
1018 1044
1045void smtc_ipi_replay(void)
1046{
1047 raw_local_irq_disable();
1048 __smtc_ipi_replay();
1049}
1050
1019EXPORT_SYMBOL(smtc_ipi_replay); 1051EXPORT_SYMBOL(smtc_ipi_replay);
1020 1052
1021void smtc_idle_loop_hook(void) 1053void smtc_idle_loop_hook(void)
1022{ 1054{
1023#ifdef SMTC_IDLE_HOOK_DEBUG 1055#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
1024 int im; 1056 int im;
1025 int flags; 1057 int flags;
1026 int mtflags; 1058 int mtflags;
@@ -1113,14 +1145,20 @@ void smtc_idle_loop_hook(void)
1113 local_irq_restore(flags); 1145 local_irq_restore(flags);
1114 if (pdb_msg != &id_ho_db_msg[0]) 1146 if (pdb_msg != &id_ho_db_msg[0])
1115 printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); 1147 printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
1116#endif /* SMTC_IDLE_HOOK_DEBUG */ 1148#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
1117 1149
1118 /* 1150 /*
1119 * Replay any accumulated deferred IPIs. If "Instant Replay" 1151 * Replay any accumulated deferred IPIs. If "Instant Replay"
1120 * is in use, there should never be any. 1152 * is in use, there should never be any.
1121 */ 1153 */
1122#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY 1154#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
1123 smtc_ipi_replay(); 1155 {
1156 unsigned long flags;
1157
1158 local_irq_save(flags);
1159 __smtc_ipi_replay();
1160 local_irq_restore(flags);
1161 }
1124#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ 1162#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
1125} 1163}
1126 1164