diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-01 00:24:54 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-01 00:24:54 -0400 |
commit | bc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775 (patch) | |
tree | 427fcf2a7287c16d4b5aa6cbf494d59579a6a8b1 /arch/mips/kernel/smtc.c | |
parent | 3d29cdff999c37b3876082278a8134a0642a02cd (diff) | |
parent | dc87c3985e9b442c60994308a96f887579addc39 (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.c | 84 |
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 | ||
76 | void ipi_decode(struct smtc_ipi *); | 78 | void ipi_decode(struct smtc_ipi *); |
77 | static void post_direct_ipi(int cpu, struct smtc_ipi *pipi); | 79 | static void post_direct_ipi(int cpu, struct smtc_ipi *pipi); |
78 | static void setup_cross_vpe_interrupts(void); | 80 | static void setup_cross_vpe_interrupts(unsigned int nvpe); |
79 | void init_smtc_stats(void); | 81 | void 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 | ||
149 | static int hang_trig = 0; | 148 | static int hang_trig = 0; |
150 | 149 | ||
@@ -171,12 +170,15 @@ __setup("tintq=", tintq); | |||
171 | 170 | ||
172 | int imstuckcount[2][8]; | 171 | int 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 */ |
174 | int vpemask[2][8] = {{0,1,1,0,0,0,0,1},{0,1,0,0,0,0,0,1}}; | 173 | int vpemask[2][8] = { |
174 | {0, 0, 1, 0, 0, 0, 0, 1}, | ||
175 | {0, 0, 0, 0, 0, 0, 0, 1} | ||
176 | }; | ||
175 | int tcnoprog[NR_CPUS]; | 177 | int tcnoprog[NR_CPUS]; |
176 | static atomic_t idle_hook_initialized = {0}; | 178 | static atomic_t idle_hook_initialized = {0}; |
177 | static int clock_hang_reported[NR_CPUS]; | 179 | static 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) | |||
610 | int setup_irq_smtc(unsigned int irq, struct irqaction * new, | 611 | int 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 | ||
969 | static struct irqaction irq_ipi; | 978 | static struct irqaction irq_ipi; |
970 | 979 | ||
971 | static void setup_cross_vpe_interrupts(void) | 980 | static 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 | ||
992 | void smtc_ipi_replay(void) | 1009 | static 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 | ||
1045 | void smtc_ipi_replay(void) | ||
1046 | { | ||
1047 | raw_local_irq_disable(); | ||
1048 | __smtc_ipi_replay(); | ||
1049 | } | ||
1050 | |||
1019 | EXPORT_SYMBOL(smtc_ipi_replay); | 1051 | EXPORT_SYMBOL(smtc_ipi_replay); |
1020 | 1052 | ||
1021 | void smtc_idle_loop_hook(void) | 1053 | void 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 | ||